如何在通知中处理混合RTL和LTR语言?

and*_*per 9 android hebrew android-notifications android-support-library rtl-language

背景

Android 4.3增加了对RTL(从右到左)语言的大量支持,例如希伯来语和阿拉伯语.

问题

即使有"textDirection","layoutDirection"和"gravity",我找不到通知构建器的等价物,甚至在兼容性库中也找不到.

这意味着如果一起有希伯来语和英语单词,则顺序错误.例如(为简单起见,我用英文写):

而不是"X叫Y",你得到"Y叫X"(假设"被称为"是希伯来语中的一个单词),因为该字符串应该采用以下格式:

<string name="notification">%1$s called %2$s</string>
Run Code Online (Sandbox Code Playgroud)

注意:X和Y可以是RTL或LTR字(和偶数).

要求是在希伯来语中,右边的单词应该是X,然后单词"被叫"(当然是希伯来语),然后是左边的Y. 正如我试图在英语类比例子中展示的那样,情况正好相反.

我试过的

一个.我试图搜索文档,我发现的是我可能需要覆盖布局,但这不是一个好的解决方案.原因:

  1. 我可能不会使用Android的正确样式.
  2. 对于可能使用不同样式的下一个Android版本来说,这不是未来的证据.
  3. 它不支持自动收报机文本.

湾 我还试图调查哪些特殊字符会强制文本方向不同,并且通过在显示的文本的开头和结尾添加'\ u200f'来起作用,但它有一些缺陷:

  1. 它没有其他属性那么灵活.
  2. 我不确定我是否使用官方方式来处理这个问题.
  3. 我每次使用通知时都需要添加此项
  4. 它对tickerText完全不起作用.仅适用于通知,即便如此,并非适用于所有情况.

这是一个示例代码:

/** prepares a string to be shown in a notification, so that it will be shown even on RTL languages */
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public static String prepareNotificationText(final Context context, final String text) {
    if (VERSION.SDK_INT < VERSION_CODES.JELLY_BEAN_MR1)
        return text;
    final boolean isRTL = context.getResources().getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
    if (!isRTL)
        return text;
    return '\u200f' + text + '\u200f';
}
Run Code Online (Sandbox Code Playgroud)

C.我也可以在字符串中的'1'和'2'之间切换,但是这并不能处理所有情况,而且它对翻译者来说更加困惑.

这个问题

有没有办法让通知构建器正确处理文本(对于通知和TickerText)?

任何方式调整它,而不实际为通知(或更改字符串)创建全新的布局,这可能不是Android的相同原生风格?

处理这种事情的官方方式是什么?

and*_*per 5

好的,根据这个这个这个找到了答案。

\n\n

对于上述情况:

\n\n

%1$s 已致电 %2$s

\n\n

为了将其正确更改为希伯来语,您需要添加特殊字符“\\u200f”,如下所示:

\n\n
  <string name="notification">%1$s \xd7\x94\xd7\xaa\xd7\xa7\xd7\xa9\xd7\xa8 \xd7\x9c %2$s</string>\n\n\n    NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);\n    if (VERSION.SDK_INT >= VERSION_CODES.O) {\n        String id = "my_channel_01";\n        CharSequence name = "channelName";// getString(R.string.channel_name);\n        String description = "channelDesc";//getString(R.string.channel_description);\n        int importance = NotificationManager.IMPORTANCE_LOW;\n        NotificationChannel channel = new NotificationChannel(id, name, importance);\n        channel.setDescription(description);\n        channel.enableLights(true);\n        channel.setLightColor(Color.RED);\n        channel.enableVibration(true);\n        channel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});\n        notificationManager.createNotificationChannel(channel);\n    }\n    Intent resultIntent = new Intent(this, MainActivity.class);\n    PendingIntent resultPendingIntent =\n            PendingIntent.getActivity(\n                    this,\n                    0,\n                    resultIntent,\n                    PendingIntent.FLAG_UPDATE_CURRENT\n            );\n\n    String[] names1 = new String[]{"\xd7\x9e\xd7\xa9\xd7\x94", "Moses"};\n    String[] names2 = new String[]{"\xd7\x93\xd7\x95\xd7\x93", "David"};\n    for (int i = 0; i < 2; ++i) {\n        for (int j = 0; j < 2; ++j) {\n            String name1, name2;\n            name1 = names1[i];\n            name2 = names2[j];\n            name1 = "\\u200f" + name1 + "\\u200f";\n            name2 = "\\u200f" + name2 + "\\u200f";\n\n            final String text = getString(R.string.notification, name1, name2);\n            NotificationCompat.Builder mBuilder =\n                    new NotificationCompat.Builder(this, "TEST")\n                            .setSmallIcon(R.mipmap.ic_launcher)\n                            .setContentTitle(text)\n                            .setContentIntent(resultPendingIntent)\n                            .setChannelId("my_channel_01")\n                            .setContentText(text);\n            int notificationId = i*2+j;\n            notificationManager.notify(notificationId, mBuilder.build());\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

在选择使用此解决方案之前,您还可以检查当前区域设置是否为 RTL。例子:

\n\n
public static boolean isRTL() {\n    return\n            Character.getDirectionality(Locale.getDefault().getDisplayName().charAt(0)) ==\n                    Character.DIRECTIONALITY_RIGHT_TO_LEFT;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

结果:

\n\n

在此输入图像描述

\n