LocalizationManager_Language.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. using UnityEngine;
  2. using System.Collections.Generic;
  3. using System.Text.RegularExpressions;
  4. using System.Linq;
  5. using System.Globalization;
  6. using System.Collections;
  7. namespace I2.Loc
  8. {
  9. public static partial class LocalizationManager
  10. {
  11. #region Variables: CurrentLanguage
  12. public static string CurrentLanguage
  13. {
  14. get {
  15. InitializeIfNeeded();
  16. return mCurrentLanguage;
  17. }
  18. set {
  19. InitializeIfNeeded();
  20. string SupportedLanguage = GetSupportedLanguage(value);
  21. if (!string.IsNullOrEmpty(SupportedLanguage) && mCurrentLanguage != SupportedLanguage)
  22. {
  23. SetLanguageAndCode(SupportedLanguage, GetLanguageCode(SupportedLanguage));
  24. }
  25. }
  26. }
  27. public static string CurrentLanguageCode
  28. {
  29. get {
  30. InitializeIfNeeded();
  31. return mLanguageCode; }
  32. set {
  33. InitializeIfNeeded();
  34. if (mLanguageCode != value)
  35. {
  36. string LanName = GetLanguageFromCode(value);
  37. if (!string.IsNullOrEmpty(LanName))
  38. SetLanguageAndCode(LanName, value);
  39. }
  40. }
  41. }
  42. // "English (United States)" (get returns "United States")
  43. // when set "Canada", the new language code will be "English (Canada)"
  44. public static string CurrentRegion
  45. {
  46. get {
  47. var Lan = CurrentLanguage;
  48. int idx = Lan.IndexOfAny("/\\".ToCharArray());
  49. if (idx > 0)
  50. return Lan.Substring(idx + 1);
  51. idx = Lan.IndexOfAny("[(".ToCharArray());
  52. int idx2 = Lan.LastIndexOfAny("])".ToCharArray());
  53. if (idx > 0 && idx != idx2)
  54. return Lan.Substring(idx + 1, idx2 - idx - 1);
  55. else
  56. return string.Empty;
  57. }
  58. set {
  59. var Lan = CurrentLanguage;
  60. int idx = Lan.IndexOfAny("/\\".ToCharArray());
  61. if (idx > 0)
  62. {
  63. CurrentLanguage = Lan.Substring(idx + 1) + value;
  64. return;
  65. }
  66. idx = Lan.IndexOfAny("[(".ToCharArray());
  67. int idx2 = Lan.LastIndexOfAny("])".ToCharArray());
  68. if (idx > 0 && idx != idx2)
  69. Lan = Lan.Substring(idx);
  70. CurrentLanguage = Lan + "(" + value + ")";
  71. }
  72. }
  73. // "en-US" (get returns "US") (when set "CA", the new language code will be "en-CA")
  74. public static string CurrentRegionCode
  75. {
  76. get {
  77. var code = CurrentLanguageCode;
  78. int idx = code.IndexOfAny(" -_/\\".ToCharArray());
  79. return idx < 0 ? string.Empty : code.Substring(idx + 1);
  80. }
  81. set {
  82. var code = CurrentLanguageCode;
  83. int idx = code.IndexOfAny(" -_/\\".ToCharArray());
  84. if (idx > 0)
  85. code = code.Substring(0, idx);
  86. CurrentLanguageCode = code + "-" + value;
  87. }
  88. }
  89. public static CultureInfo CurrentCulture
  90. {
  91. get
  92. {
  93. return mCurrentCulture;
  94. }
  95. }
  96. static string mCurrentLanguage;
  97. static string mLanguageCode;
  98. static CultureInfo mCurrentCulture;
  99. static bool mChangeCultureInfo = false;
  100. public static bool IsRight2Left = false;
  101. public static bool HasJoinedWords = false; // Some languages (e.g. Chinese, Japanese and Thai) don't add spaces to their words (all characters are placed toguether)
  102. #endregion
  103. public static void SetLanguageAndCode(string LanguageName, string LanguageCode, bool RememberLanguage = true, bool Force = false)
  104. {
  105. if (mCurrentLanguage != LanguageName || mLanguageCode != LanguageCode || Force)
  106. {
  107. if (RememberLanguage)
  108. PersistentStorage.SetSetting_String("I2 Language", LanguageName);
  109. mCurrentLanguage = LanguageName;
  110. mLanguageCode = LanguageCode;
  111. mCurrentCulture = CreateCultureForCode(LanguageCode);
  112. if (mChangeCultureInfo)
  113. SetCurrentCultureInfo();
  114. IsRight2Left = IsRTL(mLanguageCode);
  115. HasJoinedWords = GoogleLanguages.LanguageCode_HasJoinedWord(mLanguageCode);
  116. LocalizeAll(Force);
  117. }
  118. }
  119. static CultureInfo CreateCultureForCode(string code)
  120. {
  121. #if !NETFX_CORE
  122. try
  123. {
  124. return CultureInfo.CreateSpecificCulture(code);
  125. }
  126. catch (System.Exception)
  127. {
  128. return CultureInfo.InvariantCulture;
  129. }
  130. #else
  131. return CultureInfo.InvariantCulture;
  132. #endif
  133. }
  134. public static void EnableChangingCultureInfo(bool bEnable)
  135. {
  136. if (!mChangeCultureInfo && bEnable)
  137. SetCurrentCultureInfo();
  138. mChangeCultureInfo = bEnable;
  139. }
  140. static void SetCurrentCultureInfo()
  141. {
  142. #if !NETFX_CORE
  143. System.Threading.Thread.CurrentThread.CurrentCulture = mCurrentCulture;
  144. #endif
  145. }
  146. static void SelectStartupLanguage()
  147. {
  148. if (Sources.Count == 0)
  149. return;
  150. // Use the system language if there is a source with that language,
  151. // or pick any of the languages provided by the sources
  152. string SavedLanguage = PersistentStorage.GetSetting_String("I2 Language", string.Empty);
  153. string SysLanguage = GetCurrentDeviceLanguage();
  154. // Try selecting the System Language
  155. // But fallback to the first language found if the System Language is not available in any source
  156. if (!string.IsNullOrEmpty(SavedLanguage) && HasLanguage(SavedLanguage, Initialize: false, SkipDisabled:true))
  157. {
  158. SetLanguageAndCode(SavedLanguage, GetLanguageCode(SavedLanguage));
  159. return;
  160. }
  161. if (!Sources [0].IgnoreDeviceLanguage)
  162. {
  163. // Check if the device language is supported.
  164. // Also recognize when not region is set ("English (United State") will be used if sysLanguage is "English")
  165. string ValidLanguage = GetSupportedLanguage (SysLanguage, true);
  166. if (!string.IsNullOrEmpty (ValidLanguage)) {
  167. SetLanguageAndCode (ValidLanguage, GetLanguageCode (ValidLanguage), false);
  168. return;
  169. }
  170. }
  171. //--[ Use first language that its not disabled ]-----------
  172. for (int i = 0, imax = Sources.Count; i < imax; ++i)
  173. if (Sources[i].mLanguages.Count > 0)
  174. {
  175. for (int j = 0; j < Sources[i].mLanguages.Count; ++j)
  176. if (Sources[i].mLanguages[j].IsEnabled())
  177. {
  178. SetLanguageAndCode(Sources[i].mLanguages[j].Name, Sources[i].mLanguages[j].Code, false);
  179. return;
  180. }
  181. }
  182. }
  183. public static bool HasLanguage( string Language, bool AllowDiscartingRegion = true, bool Initialize=true, bool SkipDisabled=true )
  184. {
  185. if (Initialize)
  186. InitializeIfNeeded();
  187. // First look for an exact match
  188. for (int i=0, imax=Sources.Count; i<imax; ++i)
  189. if (Sources[i].GetLanguageIndex(Language, false, SkipDisabled) >=0)
  190. return true;
  191. // Then allow matching "English (Canada)" to "english"
  192. if (AllowDiscartingRegion)
  193. {
  194. for (int i=0, imax=Sources.Count; i<imax; ++i)
  195. if (Sources[i].GetLanguageIndex(Language, true, SkipDisabled) >=0)
  196. return true;
  197. }
  198. return false;
  199. }
  200. // Returns the provided language or a similar one without the Region
  201. //(e.g. "English (Canada)" could be mapped to "english" or "English (United States)" if "English (Canada)" is not found
  202. public static string GetSupportedLanguage( string Language, bool ignoreDisabled=false )
  203. {
  204. // First try finding the language that matches one of the official languages
  205. string code = GoogleLanguages.GetLanguageCode(Language, false);
  206. if (!string.IsNullOrEmpty(code))
  207. {
  208. // First try finding if the exact language code is in one source
  209. for (int i = 0, imax = Sources.Count; i < imax; ++i)
  210. {
  211. int Idx = Sources[i].GetLanguageIndexFromCode(code, true, ignoreDisabled);
  212. if (Idx >= 0)
  213. return Sources[i].mLanguages[Idx].Name;
  214. }
  215. // If not, try checking without the region
  216. for (int i = 0, imax = Sources.Count; i < imax; ++i)
  217. {
  218. int Idx = Sources[i].GetLanguageIndexFromCode(code, false, ignoreDisabled);
  219. if (Idx >= 0)
  220. return Sources[i].mLanguages[Idx].Name;
  221. }
  222. }
  223. // If not found, then try finding an exact match for the name
  224. for (int i=0, imax=Sources.Count; i<imax; ++i)
  225. {
  226. int Idx = Sources[i].GetLanguageIndex(Language, false, ignoreDisabled);
  227. if (Idx>=0)
  228. return Sources[i].mLanguages[Idx].Name;
  229. }
  230. // Then allow matching "English (Canada)" to "english"
  231. for (int i=0, imax=Sources.Count; i<imax; ++i)
  232. {
  233. int Idx = Sources[i].GetLanguageIndex(Language, true, ignoreDisabled);
  234. if (Idx>=0)
  235. return Sources[i].mLanguages[Idx].Name;
  236. }
  237. return string.Empty;
  238. }
  239. public static string GetLanguageCode( string Language )
  240. {
  241. if (Sources.Count==0)
  242. UpdateSources();
  243. for (int i=0, imax=Sources.Count; i<imax; ++i)
  244. {
  245. int Idx = Sources[i].GetLanguageIndex(Language);
  246. if (Idx>=0)
  247. return Sources[i].mLanguages[Idx].Code;
  248. }
  249. return string.Empty;
  250. }
  251. public static string GetLanguageFromCode( string Code, bool exactMatch=true )
  252. {
  253. if (Sources.Count==0)
  254. UpdateSources();
  255. for (int i=0, imax=Sources.Count; i<imax; ++i)
  256. {
  257. int Idx = Sources[i].GetLanguageIndexFromCode(Code, exactMatch);
  258. if (Idx>=0)
  259. return Sources[i].mLanguages[Idx].Name;
  260. }
  261. return string.Empty;
  262. }
  263. public static List<string> GetAllLanguages ( bool SkipDisabled = true )
  264. {
  265. if (Sources.Count==0)
  266. UpdateSources();
  267. List<string> Languages = new List<string> ();
  268. for (int i=0, imax=Sources.Count; i<imax; ++i)
  269. {
  270. Languages.AddRange(Sources[i].GetLanguages(SkipDisabled).Where(x=>!Languages.Contains(x)));
  271. }
  272. return Languages;
  273. }
  274. public static List<string> GetAllLanguagesCode(bool allowRegions=true, bool SkipDisabled = true)
  275. {
  276. List<string> Languages = new List<string>();
  277. for (int i = 0, imax = Sources.Count; i < imax; ++i)
  278. {
  279. Languages.AddRange(Sources[i].GetLanguagesCode(allowRegions, SkipDisabled).Where(x => !Languages.Contains(x)));
  280. }
  281. return Languages;
  282. }
  283. public static bool IsLanguageEnabled(string Language)
  284. {
  285. for (int i = 0, imax = Sources.Count; i < imax; ++i)
  286. if (!Sources[i].IsLanguageEnabled(Language))
  287. return false;
  288. return true;
  289. }
  290. static void LoadCurrentLanguage()
  291. {
  292. for (int i = 0; i < Sources.Count; ++i)
  293. {
  294. var iCurrentLang = Sources[i].GetLanguageIndex(mCurrentLanguage, true, false);
  295. Sources[i].LoadLanguage(iCurrentLang, true, true, true, false);
  296. }
  297. }
  298. // This function should only be called from within the Localize Inspector to temporaly preview that Language
  299. public static void PreviewLanguage(string NewLanguage)
  300. {
  301. mCurrentLanguage = NewLanguage;
  302. mLanguageCode = GetLanguageCode(mCurrentLanguage);
  303. IsRight2Left = IsRTL(mLanguageCode);
  304. HasJoinedWords = GoogleLanguages.LanguageCode_HasJoinedWord(mLanguageCode);
  305. }
  306. }
  307. }