已合并
fix:I18nManager Optimization #1958
zheng-jun-feng创建于 2025年12月30日
fix:I18nManager Optimization #1958
已合并
zheng-jun-feng创建于 2025年12月30日
共 2 个文件变更+92-12
@@ -9,6 +9,8 @@
9 */9 */
10 10 
11import NativeI18nManager from 'react-native/Libraries/ReactNative/NativeI18nManager';11import NativeI18nManager from 'react-native/Libraries/ReactNative/NativeI18nManager';
12+import RCTDeviceEventEmitter from 'react-native/Libraries/EventEmitter/RCTDeviceEventEmitter';
13+import type {EventSubscription} from 'react-native/Libraries/vendor/emitter/EventEmitter';
12 14 
13const i18nConstants: {|15const i18nConstants: {|
14 doLeftAndRightSwapInRTL: boolean,16 doLeftAndRightSwapInRTL: boolean,
@@ -16,6 +18,12 @@ const i18nConstants: {|
16 localeIdentifier?: ?string,18 localeIdentifier?: ?string,
17|} = getI18nManagerConstants();19|} = getI18nManagerConstants();
18 20 
21+let harmonyI18nConstants: {|
22+ doLeftAndRightSwapInRTL: boolean,
23+ isRTL: boolean,
24+ localeIdentifier?: ?string,
25+|} | null = null;
26+ 
19function getI18nManagerConstants() {27function getI18nManagerConstants() {
20 if (NativeI18nManager) {28 if (NativeI18nManager) {
21 const {isRTL, doLeftAndRightSwapInRTL, localeIdentifier} =29 const {isRTL, doLeftAndRightSwapInRTL, localeIdentifier} =
@@ -29,15 +37,46 @@ function getI18nManagerConstants() {
29 };37 };
30}38}
31 39 
40+function getHarmonyI18nManagerConstants() {
41+ if (harmonyI18nConstants == null) {
42+ harmonyI18nConstants = getI18nManagerConstants();
43+ }
44+ return harmonyI18nConstants;
45+}
46+ 
47+function invalidateHarmonyI18nConstantsCache() {
48+ harmonyI18nConstants = null;
49+}
50+ 
51+let languageChangeListener: ?EventSubscription = null;
52+ 
53+function addLanguageListener() {
54+ languageChangeListener = RCTDeviceEventEmitter.addListener("i18nManagerLanguageChanged", (event) => {
55+ invalidateHarmonyI18nConstantsCache();
56+ });
57+}
58+ 
59+function setupLanguageChangeListener() {
60+ if (!languageChangeListener) {
61+ try {
62+ if (RCTDeviceEventEmitter && typeof RCTDeviceEventEmitter.addListener === 'function') {
63+ addLanguageListener();
64+ }
65+ } catch (error) {
66+ console.error('Failed to register listener:', error);
67+ }
68+ }
69+}
70+ 
71+setupLanguageChangeListener();
72+ 
32module.exports = {73module.exports = {
33 getConstants: (): {|74 getConstants: (): {|
34 doLeftAndRightSwapInRTL: boolean,75 doLeftAndRightSwapInRTL: boolean,
35 isRTL: boolean,76 isRTL: boolean,
36 localeIdentifier: ?string,77 localeIdentifier: ?string,
37 |} => {78 |} => {
38- // RNOH patch79+ return getHarmonyI18nManagerConstants();
39- // return i18nConstants;
40- return Platform.OS === "harmony" ? getI18nManagerConstants() : i18nConstants;
41 },80 },
42 81 
43 allowRTL: (shouldAllow: boolean) => {82 allowRTL: (shouldAllow: boolean) => {
@@ -46,6 +85,7 @@ module.exports = {
46 }85 }
47 86 
48 NativeI18nManager.allowRTL(shouldAllow);87 NativeI18nManager.allowRTL(shouldAllow);
88+ invalidateHarmonyI18nConstantsCache();
49 },89 },
50 90 
51 forceRTL: (shouldForce: boolean) => {91 forceRTL: (shouldForce: boolean) => {
@@ -54,6 +94,7 @@ module.exports = {
54 }94 }
55 95 
56 NativeI18nManager.forceRTL(shouldForce);96 NativeI18nManager.forceRTL(shouldForce);
97+ invalidateHarmonyI18nConstantsCache();
57 },98 },
58 99 
59 swapLeftAndRightInRTL: (flipStyles: boolean) => {100 swapLeftAndRightInRTL: (flipStyles: boolean) => {
@@ -62,17 +103,14 @@ module.exports = {
62 }103 }
63 104 
64 NativeI18nManager.swapLeftAndRightInRTL(flipStyles);105 NativeI18nManager.swapLeftAndRightInRTL(flipStyles);
106+ invalidateHarmonyI18nConstantsCache();
65 },107 },
66 108 
67- // RNOH patch
68 get isRTL() {109 get isRTL() {
69- return Platform.OS === "harmony" ? getI18nManagerConstants().isRTL : i18nConstants.isRTL;110+ return getHarmonyI18nManagerConstants().isRTL;
70 },111 },
71- // isRTL: i18nConstants.isRTL,
72 112 
73- // RNOH patch
74 get doLeftAndRightSwapInRTL() {113 get doLeftAndRightSwapInRTL() {
75- return Platform.OS === "harmony" ? getI18nManagerConstants().doLeftAndRightSwapInRTL : i18nConstants.doLeftAndRightSwapInRTL;114+ return getHarmonyI18nManagerConstants().doLeftAndRightSwapInRTL;
76 },115 },
77- // doLeftAndRightSwapInRTL: i18nConstants.doLeftAndRightSwapInRTL,
78};116};
@@ -5,6 +5,7 @@
5 * LICENSE-MIT file in the root directory of this source tree.5 * LICENSE-MIT file in the root directory of this source tree.
6 */6 */
7 7 
8+import type { TurboModuleContext } from '../../RNOH/TurboModule';
8import I18n from '@ohos.i18n';9import I18n from '@ohos.i18n';
9import { TurboModule } from "../../RNOH/TurboModule";10import { TurboModule } from "../../RNOH/TurboModule";
10 11 
@@ -13,16 +14,50 @@ export class I18nManagerTurboModule extends TurboModule {
13 14 
14 private RTLAllowed = true;15 private RTLAllowed = true;
15 private RTLForced = false;16 private RTLForced = false;
17+ private lastLanguage: string | null = null;
18+ private cleanUpCallbacks: (() => void)[] = [];
19+ 
20+ constructor(protected ctx: TurboModuleContext) {
21+ super(ctx);
22+ this.lastLanguage = this.ctx.uiAbilityContext.config.language;
23+ this.subscribeToLanguageChanges();
24+ }
25+ 
26+ private subscribeToLanguageChanges() {
27+ // Monitor for configuration update events and detect language changes.
28+ const onConfigurationUpdate = (newConfig: any) => {
29+ const newLanguage = newConfig?.language || this.ctx.uiAbilityContext.config.language;
30+ 
31+ if (this.lastLanguage !== newLanguage) {
32+ this.lastLanguage = newLanguage;
33+ const newIsRTL = this.RTLForced || (this.RTLAllowed && I18n.isRTL(newLanguage));
34+ const eventPayload = {
35+ localeIdentifier: newLanguage,
36+ isRTL: newIsRTL
37+ };
38+ this.ctx.rnInstance.emitDeviceEvent("i18nManagerLanguageChanged", eventPayload);
39+ this.ctx.rnInstance.updateRTL(newIsRTL);
40+ }
41+ };
42+ 
43+ this.cleanUpCallbacks.push(
44+ this.ctx.rnInstance.subscribeToLifecycleEvents("CONFIGURATION_UPDATE", onConfigurationUpdate)
45+ );
46+ }
16 47 
17 get isRTL() {48 get isRTL() {
18- return this.RTLForced || (this.RTLAllowed && I18n.isRTL(this.ctx.uiAbilityContext.config.language));49+ const currentLanguage = this.lastLanguage || this.ctx.uiAbilityContext.config.language;
50+ return this.RTLForced || (this.RTLAllowed && I18n.isRTL(currentLanguage));
19 }51 }
20 52 
21 getConstants() {53 getConstants() {
54+ const currentLanguage = this.lastLanguage || this.ctx.uiAbilityContext.config.language;
55+ const currentIsRTL = this.RTLForced || (this.RTLAllowed && I18n.isRTL(currentLanguage));
56+ 
22 return {57 return {
23- isRTL: this.isRTL,58+ isRTL: currentIsRTL,
24 doLeftAndRightSwapInRTL: true,59 doLeftAndRightSwapInRTL: true,
25- localeIdentifier: this.ctx.uiAbilityContext.config.language60+ localeIdentifier: currentLanguage
26 };61 };
27 }62 }
28 63 
@@ -35,4 +70,11 @@ export class I18nManagerTurboModule extends TurboModule {
35 this.RTLForced = force;70 this.RTLForced = force;
36 this.ctx.rnInstance.updateRTL(this.isRTL);71 this.ctx.rnInstance.updateRTL(this.isRTL);
37 }72 }
73+ 
74+ __onDestroy__() {
75+ super.__onDestroy__();
76+ this.cleanUpCallbacks.forEach(cb => cb());
77+ this.cleanUpCallbacks = [];
78+ }
38}79}
80+