用力抱一下APP国际化

2020-12-07  本文已影响0人  Find_A_Way
image
APP国际化,说的直白应该也叫本土化或者本地化,如果你的应用上线到谷歌应用市场,那么应该做好本地化的支持,用来支持不同语言及地区的风俗习惯,当然也要结合公司拓展的海外市场需要,那么对于一款应用,至少应该做到多语言和多布局的支持。
最近忙于阿拉伯语适配工作,自己便去搜罗和整理了一些,也踩过很多的坑,如果你的APP在做国际化支持,那么推荐你阅读下,这也许是篇值得参考的文章,若对你有所帮助的话,那就反手点个大大的赞哇!

国际化资源

资源是指文本字符串、布局、声音、图形和你的Android 应用需要的任何其他静态数据。

res/
    layout/
        main.xml (Default layout)
    layout-ar/
        main.xml (Specific layout for Arabic)
    layout-ldrtl/
        main.xml (Any "right-to-left" language, except
                  for Arabic, because the "ar" language qualifier
                  has a higher precedence.)

针对于其他资源,譬如drawable图片、anim动画、raw静态资源和xml的本地化同样可以通过语言区域作为划分,也可以通过布局方向作为区分,所以对于本地化来说我们可以结合多种方式灵活运用他们。AS创建Resource File或者Resource Directory系统已经提供选择语言和一些特殊的区域。如下图:


image

国际化字符串

 ../values-en/strings.xml 英语
 <string name="my_topic_btn">My Topic</string>
 ../values-ar/strings.xml 阿拉伯语
 <string name="my_topic_btn">موضوعي</string>
 ../values-fr/strings.xml 法语
 <string name="my_topic_btn">mon sujet</string>
 ../values-hi/strings.xml 印度语
 <string name = "my_topic_btn"> मेरा विषय</string>
// 占位符最好不要被翻译,特别是阿拉伯语
 <string name="admission">
   تطبي <xliff:g id="xliff_admission">%1$s</xliff:g> للقبول
 </string>
// url连接地址不要做翻译
<string name="web_url">
  Visit us at <xliff:g id="main_web_url">http://my/app/home.html</xliff:g>
</string>
// 用户名不要做翻译
<string name="user_name">
  username: <xliff:g id="name">Herry</xliff:g>
</string>

LTR与RTL布局

我们一般的阅读习惯都是从左往右,即LTR(left to right),这是Android系统的默认支持的布局方式,除此之外,当targetSdkVersion 设为 17 或更高版本,则系统会激活和使用各种 RTL API,所谓的RTL即从右往左的布局,用来支持中东国家的阅读习惯,常见的语种有阿拉伯语、波斯语、希伯来语等等。
Android控件已经大部分支持RTL布局了,但是一些自定义的控件需要自己做适配。通常情况只需要在<application>标签增加 android:supportsRtl="true",就可启用RTL API来支持RTL布局,具体的适配方案后面会详细讲到。

image

RTL布局预览

Android Studio默认已经为我们提供了对应语言区域的预览,打开预览的界面Locale for Preview,默认会显示Default(en-us),使用的布局为LTR,若我们使用到了阿拉伯语等RTL语言,预览可以选择对应的ar语或者RTL语言,如下图:

image

伪语言区域

Android系统平台默认提供了两种伪语言区域,英语 (XA)和AR (XB),分别表示从左到右 (LTR) 和从右到左 (RTL) 显示的语言。即使我们不使用 RTL 语言,伪语言区域也可以帮助我们创建应用的 RTL 版本。 部分定制手机可能不存在这两种伪语言区域。

image
英语 (XA):在基本英文界面文本中添加拉丁语重音符号,通过添加不带重音符号的文本扩展原始文本,并用方括号将每个消息单元括起来,以使扩展文本中的潜在问题暴露出来。潜在的问题可能是布局损坏和消息语法错误,表现为一个句子被分成多个部分,显示为多条由括号括住的消息。
AR (XB):将从左到右显示的原始消息的文本方向设为从右到左的方向,它会颠倒原始消息中字符的顺序。
image
要使用 Android 伪语言区域,必须运行 Android 4.3(API 级别 18)或更高版本,并在设备上启用开发者选项。在 Android Studio 中,可以通过以下配置添加到 build.gradle 文件来为特定应用启用伪语言区域.
 android {
      ...
      buildTypes {
        debug {
          pseudoLocalesEnabled true
        }
      }

RTL布局,阿拉伯语的适配

name desc chinese
android:layoutDirection the direction of layout drawing 设置组件的布局排列方向
android:textDirection the direction of the text 设置组件的文字排列方向
android:textAlignment the alignment of the text 设置文字的对齐方式
getLayoutDirectionFromLocale() the layout direction for a given Locale 获取指定地区的惯用布局方式
<application  
 android:supportsRtl="true">
</application>
 <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- 阿拉伯语言适配-->
        <item name="android:textViewStyle">@style/TextViewStyle.TextDirection</item>
        <item name="editTextStyle">@style/EditTextStyle.Alignment</item>
    </style>

    <!--阿拉伯语适配文本-->
    <style name="TextViewStyle.RTL" parent="android:Widget.TextView">
        <item name="android:textDirection">locale</item>
    </style>

    <!--阿拉伯语适配编辑框-->
    <style name="EditTextStyle.RTL" parent="@android:style/Widget.EditText">
        <item name="android:textAlignment">viewStart</item>
        <item name="android:gravity">start|center_vertical</item>
        <item name="android:textDirection">locale</item>
    </style>
..res
  ..drawable-ldrtl-xhdpi
    ..icon_logo.png
  ..drawable-ldrtl-xxhdpi
    ..icon_logo.png

第二种方式:如果是svg矢量图或者自定义的drawable,可以通过设置android:autoMirrored="true"属性,当系统检测到RTL布局时,会自动创建图片镜像。若是ImageView可以通过Drawable对象来创建镜像。

// svg创建镜像
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="20dp"
    android:height="20dp"
    android:autoMirrored="true"
    android:viewportWidth="20"
    android:viewportHeight="20">
  <path
      android:pathData="M5.5,10l3,4l7,-8"
      android:strokeLineCap="round"/>
</vector>

// ImageView创建镜像
 Drawable drawable = ContextCompat.getDrawable(context, R.drawable.logo);
 // 设置所有的返回按钮支持RTL布局
 drawable.setAutoMirrored(true);
 imageView.setImageDrawable(drawable);

// 当前布局是否为RTL布局,true RTL/false LTR
boolean isRtl = TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault()) == ViewCompat.LAYOUT_DIRECTION_RTL
if (isRtl) {
   // TODO 如果是阿拉伯语,重新计算横坐标,得到x的点击区域
   return event.getX() > getPaddingEnd() && (event.getX() < getPaddingEnd() + getCompoundDrawablesRelative()[2].getIntrinsicWidth());
   } else {
  return event.getX() > (getWidth() - getPaddingEnd() - getCompoundDrawablesRelative()[2].getIntrinsicWidth()) && (event.getX() < ((getWidth() - getPaddingEnd())));
  }
// 替换前
drawerLayout.closeDrawer(Gravity.LEFT)
// 替换后
drawerLayout.closeDrawer(GravityCompat.START)
 // 指定Local兼容RTL
 SimpleDateFormat sdf = new SimpleDateFormat(format,Locale.US);
 // 指定Local兼容RTL
 String.format(Locale.US, "%d", minutes)
<!DOCTYPE html>
<html dir="rtl">
<head> 
<meta charset="utf-8"> 
<title>RTL布局测试</title> 
</head>
<body>
<bdo>文本方向从右到左!</bdo>
</body>
</html>
    <androidx.constraintlayout.widget.Barrier
        android:id="@+id/barrier"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierDirection="start"
        app:constraint_referenced_ids="haha"/>
1.在基类的BaseActivity的setContentView方法之前重新设置语言
    public static void changeLanguage(Context context, String newLanguage) {
        Resources resources = context.getResources();
        Configuration configuration = resources.getConfiguration();
        // app locale
        Locale locale = getLocaleByLanguage(newLanguage);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            configuration.setLocale(locale);
        } else {
            configuration.locale = locale;
        }
        DisplayMetrics dm = resources.getDisplayMetrics();
        resources.updateConfiguration(configuration, dm);
        //保存当前语言
        ...
    }
2.在使用到WebView的界面,onCrate方法增加如下
 @Override
    public void onCreate(Bundle savedInstanceState) {
        // TODO 解决含有webView控件导致切换语言失效
        new WebView(this).destroy();
        super.onCreate(savedInstanceState);
    }

最后

关于本地化,个人的建议就是杜绝任何形式的硬编码字符串资源,灵活的使用语言区域限定符和布局方向限定符,某些不应该被翻译的部分应当合理的使用标记符进行标记,部分图片尽量通过系统提供的镜像API进行适配,防止apk资源包变得越来越庞大,还有一些程序使用过程中动态的方法需要通过全局搜索进行整体替换,一些第三方库这个不属于自己能完全控制的范畴,可视情况而定,所以,如果你本身有很不错的开源项目,也应该考虑下国际化。另外我很懒的,所以喜欢这篇文章的话随手点个赞吧!

上一篇 下一篇

猜你喜欢

热点阅读