Unity阿拉伯语的适配(终极版)

最近在做阿语的适配,发现网上并没有一套完整的方案,这次给大家带来一套完整的解决方案,并配上一套可扩展的代码,希望我们每个人以后再遇到阿拉伯语的适配的时候,可以使用这套终极解决方案来搞定。同时随着unity的更新,越来越多项目组使用TextMeshPro。本文提供的方案既能支持UGUI,也能支持TextmeshPro,还可以从unity2018以上都能适配成功 ,低于这个版本的我没测试。

阿拉伯文的适配最难的点在于,你搞不懂你的结果是对的还是错的,我做的时候就是参考百度翻译,最后再找懂阿语的人来校对一下。文章后面会教给大家一个简单的方法来自己去判断阿语的显示。

阿拉伯文的简介

   1.首先我们要来对阿文有一个基本的认知。阿文的显示是从右往左,右对齐。这里要注意,不只是顺序从右往左,每一个字符,也都是从右往左显示。
             原文:"ABCD EFG"   (斜体表示原始顺序)
             阿文:"GFE DCBA"   (非斜体表示正确顺序)
   2.阿拉伯语属闪含语系闪米特语族,是由28个辅音字母和12个发音符号(不包括叠音符)组成的拼音文字。书写顺序从右往左横行书写,翻阅顺序也是由右往左。阿拉伯语字母无大、小写之分,但有印刷体、手写体和艺术体之别。书写时,每个字母均有单写与连写之分。
        下图为部分辅音字母,简单点说, 28个辅音字母中的每一个都有4个字形,用于根据字母在初始,中间,最终或隔离中的位置来表示字母。(说白了就是,一个字母右4种写法,根据你的位置来决定怎么写,在适配的时候,你会看到一个字符串翻转过来以后,长得完全不一样)
   3.tashkeel(元音)
        元音我理解就像我们汉字里的拼音,一般来说,是不需要显示元音的。通常在《古兰经》、幼儿读物、阿语学习教材,或者给外国人阅读的书籍中才加元音符号。
        一个最简单的看法就是,你发现你的阿文里,上下有点点之类的时候,就表示他显示了元音
        大部分情况下,不需要显示原音
   4.数字的问题
        虽然我们日常使用的是数字叫阿拉伯数字,比如1234567890,但是实际上阿拉伯数字最初由古印度人发明,再由阿拉伯人传向欧洲,欧洲再将其现代化,人们误以为是阿拉伯人发明,所以称之为阿拉伯数
        字。实际上阿语中,有一套自己的数字系统,而且不止一套。我们在做阿语适配的时候,会将数值统一改为我们印象中的阿拉伯数字(1234567890),而不用阿拉伯文里数字。
        阿拉伯文的数值依然使用从左到右显示                                                             
   5.和英文,数字等混排的时候,英文和数值依然使用从左到右的顺序
        原文:"ABCD  hello 123  EFG"   (斜体表示原始顺序)
        阿文:"GFE 123  hello DCBA"   (非斜体表示正确顺序)
     以上5种,都是阿语语法和显示顺序的关系,网上有一个免费的插件
     也是应用范围最广的一个插件 [https://github.com/Konash/arabic-support-unity](https://github.com/Konash/arabic-support-unity)
     该插件使用简单,一句话就可以搞定
     string result = ArabicFixer.Fix(text, false, false);         

上面这些网上你也能搜索到,实际在项目中使用肯定不会这么简单
这个控件只负责转换阿语的字符,富文本,换行,混排都有些问题
来看一下他的问题
1.换行
2.富文本标签
3.英文,阿语混排
这3种情况,上述插件并不支持,都需要我们对插件做改动。每个项目组都会在自己的理解上做一些改动,但是大家都没有一套统一的解决方案。这里介绍一下我的解决方案。

我这里没有使用ArabicSupport这个插件,而是使用了RTL TextMeshPro这个方案https://github.com/pnarimani/RTLTMPro,这个方案帮我们处理好了富文本标签等效果,可以避免再做一些重复工作了。使用这个方案,再把它的适配效果移植到UGUI。

准备工作

  1. 根据unicode码查询字符
    https://symbl.cc/cn/

  2. Unicode字符库
    https://www.fuhaoku.net/blocks

  3. RTL TextMeshPro
    https://github.com/pnarimani/RTLTMPro

  4. 查看阿语真正正确的顺序
    安装好Word软件,不要用WPS,不要用WPS,word软件是为了方便我们验证阿语真正应该显示成什么样子
    打开word,复制一句阿语,然后在粘贴选项中选择"只保留文本"。然后选择"段落->从右往左文字方向"
    在这里插入图片描述
    在这里插入图片描述

    这种状态下,你看到阿语才是真正正确的阿语
    重要的事情说3遍:不要相信你在调试的时候,或者是记事本,或者是ide中看到字符串,在实际运行的时候,可能未必是你看到顺序!!!
    IDE,调试器,或者是一些记事本程序,都会自行对阿语做转换,但是转换的结果未必是正确的!!!

  5. 创建一个工具函数,用来打印字符串的unicode码,然后根据unicode码,使用 https://symbl.cc/cn/这个网站来查询对应的字符,才能看到真正的顺序

public void PrintArabicUnicode(string text)
{
    
    
    StringBuilder sb=new StringBuilder();
    for (int i=0;i<text.Length;i++)
    {
    
    
        int unicode32CodePoint = char.ConvertToUtf32(text, i);
        sb.Append(unicode32CodePoint+" ");
    }
    Debug.Log(sb.ToString());
}
//注意在这个文档里,阿语的显示顺序已经发生变化了,其实我使用的还是上面的字符串
//string se = "name_new_group_hint=اسم المجموعة (مطلوب)";
//PrintArabicUnicode(se);
//输出结果
//110 97 109 101 95 110 101 119 95 103 114 111 117 112 95 104 105 110 116 61 1575 1587 1605 32 1575 1604 1605 1580 1605 1608 1593 1577 32 40 1605 1591 1604 1608 1576 41
比如说110,对应英文字母n

在这里插入图片描述

TextMeshPro如何适配

我使用的unity2018.4,TextMeshPro(TMP)版本为1.4.1,这个版本稍微老一些,如果你使用更高级版本的unity和TMP,也可以使用
安装好TMP以后,下载RTL TextMeshPro

  1. 打开下载页https://github.com/pnarimani/RTLTMPro/releases,下载 v3.4.3.unitypackage,并且导入到项目中
    在这里插入图片描述

  2. 修改TMP源码
    对于TMP2.1以上的版本,都不需要这步,直接第3步即可
    低于2.1的版本,需要修改源码。下面介绍一下如何修改TMP的源码
    下面是插件官方给的修改方法
    在这里插入图片描述

    如果看不懂的话,按照下面的步骤去修改

  3. 首先关闭unity,在Libray/PackageCache中找到TMP源码,然后将整个文件夹剪切到Packages目录中即可
    在这里插入图片描述
    在这里插入图片描述

  4. 找到TMP_Text文件,给Text字段增加virtual关键字,然后打开 RTLTextMeshPro.cs文件,给Text增加override关键字
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  5. 使用RTLTMPro
    整个文件夹目录如下,Scene中有很多测试的demo,可以看一下,实际在使用的时候,为了节省项目资源,可以只保留Scripts目录,其他目录一律删掉
    在这里插入图片描述
    右键使用菜单时,可以发现多出了Text-RTLTMP的选项
    把TextMeshProUGUI脚本,全部替换成RTL TextMeshPro即可
    所有需要阿语的文本控件,都替换成RTL TextMeshPro
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述

  6. 讲解一下RTL TextMeshPro,它和原生的TextMeshPro比,多出了4个字段

  • Farsi:勾选以后,英文数字会变成波斯文数字,一般不用勾选
  • ForceFix:这个字段很重要,有时候阿语和英文混排的时候,如果英文字母在句首,往往会把这句话当成英文来处理,这种情况下可以勾选这个选项,来强制使用阿语来处理
  • Preserve
    Numbers:勾选以后,阿拉伯数字会使用123456789这种形式来显示,建议勾选(具体原因参照上文,阿语中有自己的数字形式,如果想用123456789这种显示数字,就需要勾选)
  • FixTags:勾选后,支持TMP的富文本标签,建议勾选

7.实践中推荐的用法

第6步是官方推荐的用法,在实际应用中发现还是有些不便利的地方,比如说force fix的勾选就不够智能上述4个选项,每次都需要去选择一下,不够智能 下面说一下,我自己是怎么使用的 新建脚本,继承TextMeshProUGUI,这样所有的文本都使用FinalText FinalText会判断字符串中是否包含阿文,如果有阿文,就会自动调用修复脚本来处理

using System.Collections;
using System.Collections.Generic;
using RTLTMPro;
using TMPro;
using UnityEngine;


public class FinalText : TextMeshProUGUI
{
    
    
    public override string text
    {
    
    
        get {
    
     return base.text; }
        set
        {
    
    
            string val = value;
            if (HasArabic(val))
            {
    
    
                isRightToLeftText = true;
                base.text = GetFixedText(val);
            }
            else
            {
    
    
                isRightToLeftText = false;
                base.text = val;
            }
        }
    }
    
    public static bool HasArabic(string str)
    {
    
    
        if (string.IsNullOrEmpty(str))
            return false;
        int strLength = str.Length;
        for (var i = 0; i < strLength; i++)
        {
    
    
            char c = str[i];
            if (isArabic(c))
            {
    
    
                return true;
            }
        }


        return false;
    }
    
    public static bool isArabic(char c)
    {
    
    
        if (c >= 0x600 && c <= 0x6ff) return true;
        if (c >= 0x750 && c <= 0x77f) return true;
        if (c >= 0xfb50 && c <= 0xfc3f) return true;
        if (c >= 0xfe70 && c <= 0xfefc) return true;
        return false;
    }
    
    protected readonly FastStringBuilder finalText = new FastStringBuilder(RTLSupport.DefaultBufferSize);


    private string GetFixedText(string input)
    {
    
    
        if (string.IsNullOrEmpty(input))
            return input;


        finalText.Clear();
        RTLSupport.FixRTL(input, finalText, false, true, true);
        finalText.Reverse();
        return finalText.ToString();
    }
}

至此,阿语的适配工作基本上就结束了,RTLTMP Pro本身处理了换行,富文本标签,英文阿语混排等问题

UGUI如何适配

上述插件,只支持TMP,对于UGUI就不支持了,查看一下源码发现,不支持的原因主要是因为UGUI不支持RTL的功能,也就是从右向左渲染。
那么如果让UGUI支持这个功能,是不是UGUI也可以用了呢?抱着试试的想法,我做了如下修改,让UGUI的顶点在渲染的时候,把顶点顺序转置

猜你喜欢

转载自blog.csdn.net/weixin_42562717/article/details/129417695