Skip to content

Fix/languages#596

Merged
Agilulfo1820 merged 2 commits intomainfrom
fix/languages
Mar 2, 2026
Merged

Fix/languages#596
Agilulfo1820 merged 2 commits intomainfrom
fix/languages

Conversation

@Agilulfo1820
Copy link
Copy Markdown
Member

@Agilulfo1820 Agilulfo1820 commented Mar 2, 2026

Removed dyanmic language loading since it was causing issues with vite

Summary by CodeRabbit

Release Notes

  • Refactor
    • Optimized language switching for improved responsiveness and performance.
    • Streamlined initialization process to reduce overhead.
    • Reduced package bundle size through dependency optimization and build configuration updates.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 2, 2026

📝 Walkthrough

Walkthrough

This refactoring converts the i18n system from dynamic runtime language loading to static resource initialization. The i18next-resources-to-backend dependency is removed, language JSONs are imported upfront, and async loadLanguage logic is replaced with synchronous changeLanguage calls throughout the codebase.

Changes

Cohort / File(s) Summary
i18n Core Infrastructure
packages/vechain-kit/i18n.ts
Migrated from dynamic language loading (via i18next-resources-to-backend) to static resources map. Imports all supported language JSONs directly and exposes them via a single resources object. Removed loadLanguage function, languageImportMap, and related dynamic import logic.
i18n Initialization Utility
packages/vechain-kit/src/utils/i18n.ts
Converted initializeI18n from async to synchronous. Replaced conditional language loading logic with iteration over all available resource languages, ensuring each has a translation bundle.
Component Language Handlers
packages/vechain-kit/src/components/AccountModal/Contents/FAQ/FAQContent.tsx, packages/vechain-kit/src/components/AccountModal/Contents/KitSettings/LanguageSettingsContent.tsx
Removed async loadLanguage invocations and error handling. Simplified language change handlers to direct synchronous calls to i18n.changeLanguage.
Provider Initialization
packages/vechain-kit/src/providers/VeChainKitProvider.tsx
Refactored i18n initialization flow from async with dynamic language loading to synchronous direct initialization. Language resolution and switching now use i18n.changeLanguage without awaiting or nested try/finally blocks.
Dependencies & Build Config
packages/vechain-kit/package.json, packages/vechain-kit/tsdown.config.ts
Version bumped to 2.6.2. Removed i18next-resources-to-backend dependency. Removed splitting: true option from tsdown build configuration.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • #594: Introduces the dynamic loadLanguage/i18next-resources-to-backend pattern that this PR reverses by switching to static resources.
  • #593: Adds Russian translation support to i18n.ts in the same file that undergoes structural refactoring in this PR.

Suggested labels

safe-to-deploy, safe-to-build

Poem

🐰 No more waiting for tongues to load,
Static resources light the road,
Async chains now straight and true,
Simpler code in every hue! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Fix/languages' is vague and generic; it lacks specificity about the actual change (removing dynamic language loading due to Vite issues). Consider a more descriptive title like 'Replace dynamic language loading with static resources for Vite compatibility' to clearly convey the main purpose.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/languages

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 2, 2026

Size Change: +316 kB (+4.35%)

Total Size: 7.6 MB

Filename Size Change
packages/vechain-kit/dist/de-BFiyX1GF.cjs.map 0 B -43.5 kB (removed) 🏆
packages/vechain-kit/dist/de-CL456uk2.mjs 0 B -60.8 kB (removed) 🏆
packages/vechain-kit/dist/de-CL456uk2.mjs.map 0 B -50 kB (removed) 🏆
packages/vechain-kit/dist/es-BqNNKHB0.mjs 0 B -60.2 kB (removed) 🏆
packages/vechain-kit/dist/es-BqNNKHB0.mjs.map 0 B -49.4 kB (removed) 🏆
packages/vechain-kit/dist/es-lVekqJvu.cjs.map 0 B -43 kB (removed) 🏆
packages/vechain-kit/dist/fr-C5OuuOPh.cjs.map 0 B -44.2 kB (removed) 🏆
packages/vechain-kit/dist/fr-PQTnQtHc.mjs 0 B -61.5 kB (removed) 🏆
packages/vechain-kit/dist/fr-PQTnQtHc.mjs.map 0 B -50.7 kB (removed) 🏆
packages/vechain-kit/dist/hi-BQ2VZQlz.mjs 0 B -81.6 kB (removed) 🏆
packages/vechain-kit/dist/hi-BQ2VZQlz.mjs.map 0 B -70.8 kB (removed) 🏆
packages/vechain-kit/dist/hi-DyR8xd6m.cjs.map 0 B -64.4 kB (removed) 🏆
packages/vechain-kit/dist/index-D1iA_I3N.d.mts 0 B -152 kB (removed) 🏆
packages/vechain-kit/dist/index-D1iA_I3N.d.mts.map 0 B -43.9 kB (removed) 🏆
packages/vechain-kit/dist/index-DLl2qqEw.d.mts 0 B -5.63 kB (removed) 🏆
packages/vechain-kit/dist/index-DLl2qqEw.d.mts.map 0 B -2.99 kB (removed) 🏆
packages/vechain-kit/dist/index.cjs 1.01 MB +624 kB (+161.74%) 🆘
packages/vechain-kit/dist/index.cjs.map 2.38 MB +782 kB (+48.94%) 🚨
packages/vechain-kit/dist/index.mjs 976 kB +625 kB (+177.91%) 🆘
packages/vechain-kit/dist/index.mjs.map 2.33 MB +782 kB (+50.63%) 🆘
packages/vechain-kit/dist/it-CcvV1IlX.mjs 0 B -59.7 kB (removed) 🏆
packages/vechain-kit/dist/it-CcvV1IlX.mjs.map 0 B -48.9 kB (removed) 🏆
packages/vechain-kit/dist/it-CtyGT5hV.cjs.map 0 B -42.4 kB (removed) 🏆
packages/vechain-kit/dist/ja-_mAa1fdP.mjs 0 B -65.2 kB (removed) 🏆
packages/vechain-kit/dist/ja-_mAa1fdP.mjs.map 0 B -54.3 kB (removed) 🏆
packages/vechain-kit/dist/ja-EfHF9V_o.cjs.map 0 B -48 kB (removed) 🏆
packages/vechain-kit/dist/ko-BeUiFlha.cjs.map 0 B -41.8 kB (removed) 🏆
packages/vechain-kit/dist/ko-CfT-gn4I.mjs 0 B -59.1 kB (removed) 🏆
packages/vechain-kit/dist/ko-CfT-gn4I.mjs.map 0 B -48.1 kB (removed) 🏆
packages/vechain-kit/dist/nl-BqGKf8N1.cjs.map 0 B -40.9 kB (removed) 🏆
packages/vechain-kit/dist/nl-ls_GRrv6.mjs 0 B -58.2 kB (removed) 🏆
packages/vechain-kit/dist/nl-ls_GRrv6.mjs.map 0 B -47.4 kB (removed) 🏆
packages/vechain-kit/dist/pt-B-R-6Hdt.mjs 0 B -58.6 kB (removed) 🏆
packages/vechain-kit/dist/pt-B-R-6Hdt.mjs.map 0 B -47.8 kB (removed) 🏆
packages/vechain-kit/dist/pt-I1a6tTFu.cjs.map 0 B -41.4 kB (removed) 🏆
packages/vechain-kit/dist/ro-Ba8tFBmh.cjs.map 0 B -42.5 kB (removed) 🏆
packages/vechain-kit/dist/ro-BoGXUy66.mjs 0 B -59.8 kB (removed) 🏆
packages/vechain-kit/dist/ro-BoGXUy66.mjs.map 0 B -49 kB (removed) 🏆
packages/vechain-kit/dist/ru-C0bvvCc8.cjs.map 0 B -54.7 kB (removed) 🏆
packages/vechain-kit/dist/ru-D-Dfg2x-.mjs 0 B -72 kB (removed) 🏆
packages/vechain-kit/dist/ru-D-Dfg2x-.mjs.map 0 B -61.2 kB (removed) 🏆
packages/vechain-kit/dist/sv-BBsWb8O5.mjs 0 B -54.9 kB (removed) 🏆
packages/vechain-kit/dist/sv-BBsWb8O5.mjs.map 0 B -44.1 kB (removed) 🏆
packages/vechain-kit/dist/sv-CDqUg0Wg.cjs.map 0 B -37.6 kB (removed) 🏆
packages/vechain-kit/dist/tr-CUjmBjJO.cjs.map 0 B -42.1 kB (removed) 🏆
packages/vechain-kit/dist/tr-DRmU0qqA.mjs 0 B -59.4 kB (removed) 🏆
packages/vechain-kit/dist/tr-DRmU0qqA.mjs.map 0 B -48.6 kB (removed) 🏆
packages/vechain-kit/dist/tw-CGmTbBO2.mjs 0 B -54.5 kB (removed) 🏆
packages/vechain-kit/dist/tw-CGmTbBO2.mjs.map 0 B -43.5 kB (removed) 🏆
packages/vechain-kit/dist/tw-Ci_2P7in.cjs.map 0 B -37.2 kB (removed) 🏆
packages/vechain-kit/dist/vi-D6xwAgyf.cjs.map 0 B -43.8 kB (removed) 🏆
packages/vechain-kit/dist/vi-tNWk5jJK.mjs 0 B -61 kB (removed) 🏆
packages/vechain-kit/dist/vi-tNWk5jJK.mjs.map 0 B -50.2 kB (removed) 🏆
packages/vechain-kit/dist/zh-BY6GpEW-.cjs.map 0 B -38.2 kB (removed) 🏆
packages/vechain-kit/dist/zh-DqPPuL6F.mjs 0 B -55.5 kB (removed) 🏆
packages/vechain-kit/dist/zh-DqPPuL6F.mjs.map 0 B -44.5 kB (removed) 🏆
packages/vechain-kit/dist/index-BQ0ary2b.d.mts 5.63 kB +5.63 kB (new file) 🆕
packages/vechain-kit/dist/index-BQ0ary2b.d.mts.map 2.99 kB +2.99 kB (new file) 🆕
packages/vechain-kit/dist/index-xnVIqqZe.d.mts 152 kB +152 kB (new file) 🆕
packages/vechain-kit/dist/index-xnVIqqZe.d.mts.map 43.9 kB +43.9 kB (new file) 🆕
ℹ️ View Unchanged
Filename Size Change
packages/vechain-kit/dist/assets 4.1 kB 0 B
packages/vechain-kit/dist/assets-BL24r-Yp.mjs 51.3 kB 0 B
packages/vechain-kit/dist/assets-BL24r-Yp.mjs.map 74.1 kB 0 B
packages/vechain-kit/dist/assets-DNJsQD7_.cjs 58.5 kB 0 B
packages/vechain-kit/dist/assets-DNJsQD7_.cjs.map 75.5 kB 0 B
packages/vechain-kit/dist/assets/index.cjs 716 B 0 B
packages/vechain-kit/dist/assets/index.d.cts 973 B 0 B
packages/vechain-kit/dist/assets/index.d.mts 973 B 0 B
packages/vechain-kit/dist/assets/index.mjs 718 B 0 B
packages/vechain-kit/dist/de-BFiyX1GF.cjs 0 B -41 B (removed) 🏆
packages/vechain-kit/dist/es-lVekqJvu.cjs 0 B -41 B (removed) 🏆
packages/vechain-kit/dist/fr-C5OuuOPh.cjs 0 B -41 B (removed) 🏆
packages/vechain-kit/dist/hi-DyR8xd6m.cjs 0 B -41 B (removed) 🏆
packages/vechain-kit/dist/index-DShXeWMB.d.cts 152 kB 0 B
packages/vechain-kit/dist/index-DShXeWMB.d.cts.map 43.9 kB 0 B
packages/vechain-kit/dist/index-I8fe7GR2.d.cts 5.63 kB 0 B
packages/vechain-kit/dist/index-I8fe7GR2.d.cts.map 2.99 kB 0 B
packages/vechain-kit/dist/index.d.cts 20.5 kB 0 B
packages/vechain-kit/dist/index.d.mts 20.5 kB 0 B
packages/vechain-kit/dist/it-CtyGT5hV.cjs 0 B -41 B (removed) 🏆
packages/vechain-kit/dist/ja-EfHF9V_o.cjs 0 B -41 B (removed) 🏆
packages/vechain-kit/dist/ko-BeUiFlha.cjs 0 B -41 B (removed) 🏆
packages/vechain-kit/dist/nl-BqGKf8N1.cjs 0 B -41 B (removed) 🏆
packages/vechain-kit/dist/pt-I1a6tTFu.cjs 0 B -41 B (removed) 🏆
packages/vechain-kit/dist/ro-Ba8tFBmh.cjs 0 B -41 B (removed) 🏆
packages/vechain-kit/dist/ru-C0bvvCc8.cjs 0 B -41 B (removed) 🏆
packages/vechain-kit/dist/sv-CDqUg0Wg.cjs 0 B -41 B (removed) 🏆
packages/vechain-kit/dist/tr-CUjmBjJO.cjs 0 B -41 B (removed) 🏆
packages/vechain-kit/dist/tw-Ci_2P7in.cjs 0 B -41 B (removed) 🏆
packages/vechain-kit/dist/utils 4.1 kB 0 B
packages/vechain-kit/dist/utils-CzaSErgL.cjs 26.2 kB 0 B
packages/vechain-kit/dist/utils-CzaSErgL.cjs.map 65.1 kB 0 B
packages/vechain-kit/dist/utils-D6wgzl57.mjs 21 kB 0 B
packages/vechain-kit/dist/utils-D6wgzl57.mjs.map 64.4 kB 0 B
packages/vechain-kit/dist/utils/index.cjs 1.98 kB 0 B
packages/vechain-kit/dist/utils/index.d.cts 3.04 kB 0 B
packages/vechain-kit/dist/utils/index.d.mts 3.04 kB 0 B
packages/vechain-kit/dist/utils/index.mjs 2 kB 0 B
packages/vechain-kit/dist/vi-D6xwAgyf.cjs 0 B -41 B (removed) 🏆
packages/vechain-kit/dist/zh-BY6GpEW-.cjs 0 B -41 B (removed) 🏆

compressed-size-action

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
packages/vechain-kit/src/utils/i18n.ts (1)

12-28: Remove duplicated branch in bundle initialization.

Both if and else execute the same addResourceBundle call, so the hasNamespace conditional is redundant and can be collapsed.

♻️ Suggested simplification
-        if (!hasNamespace) {
-            i18nInstance.addResourceBundle(
-                lang,
-                'translation',
-                resources[lang as keyof typeof resources].translation,
-                true,
-                true,
-            );
-        } else {
-            i18nInstance.addResourceBundle(
-                lang,
-                'translation',
-                resources[lang as keyof typeof resources].translation,
-                true,
-                true,
-            );
-        }
+        i18nInstance.addResourceBundle(
+            lang,
+            'translation',
+            resources[lang as keyof typeof resources].translation,
+            true,
+            true,
+        );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/vechain-kit/src/utils/i18n.ts` around lines 12 - 28, The if/else
around hasNamespace is redundant because both branches call
i18nInstance.addResourceBundle with the same arguments; remove the conditional
and invoke i18nInstance.addResourceBundle(lang, 'translation', resources[lang as
keyof typeof resources].translation, true, true) once. Keep references to
hasNamespace, i18nInstance.addResourceBundle, and resources when editing so you
update the correct initialization logic in i18n.ts.
packages/vechain-kit/i18n.ts (1)

22-45: Derive supportedLanguages from resources to prevent drift.

These are now two separate sources of truth. Deriving the language list from resources avoids future mismatches.

♻️ Suggested change
-export const supportedLanguages = [
-    'en', 'de', 'it', 'fr', 'es', 'zh', 'ja', 'ru', 'ro',
-    'vi', 'nl', 'ko', 'sv', 'tw', 'tr', 'hi', 'pt',
-];
-
 export const resources = {
   ...
 };
+
+export const supportedLanguages = Object.keys(resources);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/vechain-kit/i18n.ts` around lines 22 - 45, The supportedLanguages
array is a separate source of truth from resources and can drift; replace the
hardcoded supportedLanguages with a derived value from resources (e.g., compute
supportedLanguages using Object.keys(resources) or similar) so the list always
reflects the resource keys; update any exports/types that rely on
supportedLanguages accordingly and keep the symbol names supportedLanguages and
resources unchanged so callers continue to work.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/vechain-kit/src/providers/VeChainKitProvider.tsx`:
- Around line 454-459: Normalize and validate language inputs before syncing
state or calling i18n: introduce or use a supportedLanguages (or
defaultLanguage) set and a small normalizer function (e.g., normalizeLanguage)
that maps variants like "en-US" -> "en" and returns a fallback if unsupported;
apply this normalizer when reading storedLanguage (from
getLocalStorageItem('i18nextLng')), when initializing currentLanguage from the
language prop, and inside setLanguage(lang) before updating state or calling
i18n.changeLanguage so only validated/normalized codes are stored and used.
- Around line 460-467: The update guard is being cleared synchronously before
the async i18n.changeLanguage completes; keep isUpdatingFromPropRef.current true
until the Promise resolves by moving the assignment into the Promise.finally
handler: when you set isUpdatingFromPropRef.current = true around
i18n.changeLanguage(...) (in the blocks that call i18n.changeLanguage and then
possibly call setCurrentLanguageState), chain .finally(() => {
isUpdatingFromPropRef.current = false; }) so the guard remains active until the
language change completes; apply this pattern to all occurrences that call
i18n.changeLanguage (the block using
isUpdatingFromPropRef/currentLanguage/setCurrentLanguageState and the two other
locations noted).

---

Nitpick comments:
In `@packages/vechain-kit/i18n.ts`:
- Around line 22-45: The supportedLanguages array is a separate source of truth
from resources and can drift; replace the hardcoded supportedLanguages with a
derived value from resources (e.g., compute supportedLanguages using
Object.keys(resources) or similar) so the list always reflects the resource
keys; update any exports/types that rely on supportedLanguages accordingly and
keep the symbol names supportedLanguages and resources unchanged so callers
continue to work.

In `@packages/vechain-kit/src/utils/i18n.ts`:
- Around line 12-28: The if/else around hasNamespace is redundant because both
branches call i18nInstance.addResourceBundle with the same arguments; remove the
conditional and invoke i18nInstance.addResourceBundle(lang, 'translation',
resources[lang as keyof typeof resources].translation, true, true) once. Keep
references to hasNamespace, i18nInstance.addResourceBundle, and resources when
editing so you update the correct initialization logic in i18n.ts.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8c621d7 and 3ef878b.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (7)
  • packages/vechain-kit/i18n.ts
  • packages/vechain-kit/package.json
  • packages/vechain-kit/src/components/AccountModal/Contents/FAQ/FAQContent.tsx
  • packages/vechain-kit/src/components/AccountModal/Contents/KitSettings/LanguageSettingsContent.tsx
  • packages/vechain-kit/src/providers/VeChainKitProvider.tsx
  • packages/vechain-kit/src/utils/i18n.ts
  • packages/vechain-kit/tsdown.config.ts
💤 Files with no reviewable changes (1)
  • packages/vechain-kit/tsdown.config.ts

Comment on lines +454 to 459
const storedLanguage =
typeof window !== 'undefined'
? getLocalStorageItem('i18nextLng')
: null;
const initialLanguage = storedLanguage || currentLanguage;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Normalize language inputs before syncing state/i18n.

storedLanguage, prop language, and setLanguage(lang) are used as-is. Unsupported codes can move currentLanguage to a value with no resource bundle and break selector consistency.

🛡️ Suggested guard for supported languages
+import i18n, { supportedLanguages } from '../../i18n';
...
+const normalizeLanguage = (lng: string | null | undefined) =>
+    lng && supportedLanguages.includes(lng) ? lng : 'en';
...
-const initialLanguage = storedLanguage || currentLanguage;
+const initialLanguage = normalizeLanguage(storedLanguage || currentLanguage);
...
-if (language && !storedLanguage && language !== currentLanguage) {
+const normalizedPropLanguage = normalizeLanguage(language);
+if (!storedLanguage && normalizedPropLanguage !== currentLanguage) {
     isUpdatingFromPropRef.current = true;
-    i18n.changeLanguage(language);
-    setCurrentLanguageState(language);
+    i18n.changeLanguage(normalizedPropLanguage);
+    setCurrentLanguageState(normalizedPropLanguage);
     isUpdatingFromPropRef.current = false;
}
...
-const setLanguage = (lang: string) => {
+const setLanguage = (lang: string) => {
+    const normalized = normalizeLanguage(lang);
     isUpdatingFromPropRef.current = true;
-    i18n.changeLanguage(lang);
-    setCurrentLanguageState(lang);
+    i18n.changeLanguage(normalized);
+    setCurrentLanguageState(normalized);
     isUpdatingFromPropRef.current = false;
};

Also applies to: 477-482, 554-559

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/vechain-kit/src/providers/VeChainKitProvider.tsx` around lines 454 -
459, Normalize and validate language inputs before syncing state or calling
i18n: introduce or use a supportedLanguages (or defaultLanguage) set and a small
normalizer function (e.g., normalizeLanguage) that maps variants like "en-US" ->
"en" and returns a fallback if unsupported; apply this normalizer when reading
storedLanguage (from getLocalStorageItem('i18nextLng')), when initializing
currentLanguage from the language prop, and inside setLanguage(lang) before
updating state or calling i18n.changeLanguage so only validated/normalized codes
are stored and used.

Comment on lines +460 to +467
if (initialLanguage && i18n.language !== initialLanguage) {
isUpdatingFromPropRef.current = true;
i18n.changeLanguage(initialLanguage);
if (initialLanguage !== currentLanguage) {
setCurrentLanguageState(initialLanguage);
}
isUpdatingFromPropRef.current = false;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cd packages/vechain-kit/src/providers && head -500 VeChainKitProvider.tsx | tail -100

Repository: vechain/vechain-kit

Length of output: 3547


🏁 Script executed:

cat -n packages/vechain-kit/src/providers/VeChainKitProvider.tsx | sed -n '450,470p'

Repository: vechain/vechain-kit

Length of output: 956


🏁 Script executed:

cat -n packages/vechain-kit/src/providers/VeChainKitProvider.tsx | sed -n '470,490p'

Repository: vechain/vechain-kit

Length of output: 1086


🏁 Script executed:

cat -n packages/vechain-kit/src/providers/VeChainKitProvider.tsx | sed -n '545,565p'

Repository: vechain/vechain-kit

Length of output: 1010


🌐 Web query:

i18next v24 changeLanguage return type Promise documentation

💡 Result:

In i18next v24, changeLanguage is documented as:

  • i18next.changeLanguage(lng, callback) // -> returns a Promise [1]

And the docs’ Promise example shows the Promise resolves with the t function, i.e. effectively:

  • Return type: Promise<TFunction> [1]

Background (why it returns a Promise at all): i18next changed these async APIs (including changeLanguage) to “also return a Promise” starting in v12+ [2].

Sources: [1] [2]


Wrap changeLanguage with .finally() to keep the update guard active until the async operation resolves.

In i18next v24, changeLanguage returns a Promise<TFunction>. The current code clears isUpdatingFromPropRef synchronously, causing the guard to drop before the language change completes. Since the languageChanged listener checks this guard to prevent loops, clearing it early allows unwanted onLanguageChange callbacks to fire.

Apply this pattern to all three locations:

Corrected pattern
- i18n.changeLanguage(initialLanguage);
- ...
- isUpdatingFromPropRef.current = false;
+ void i18n.changeLanguage(initialLanguage).finally(() => {
+   isUpdatingFromPropRef.current = false;
+ });

Affects lines 460–467, 479–482, and 556–559.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (initialLanguage && i18n.language !== initialLanguage) {
isUpdatingFromPropRef.current = true;
i18n.changeLanguage(initialLanguage);
if (initialLanguage !== currentLanguage) {
setCurrentLanguageState(initialLanguage);
}
isUpdatingFromPropRef.current = false;
}
if (initialLanguage && i18n.language !== initialLanguage) {
isUpdatingFromPropRef.current = true;
void i18n.changeLanguage(initialLanguage).finally(() => {
isUpdatingFromPropRef.current = false;
});
if (initialLanguage !== currentLanguage) {
setCurrentLanguageState(initialLanguage);
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/vechain-kit/src/providers/VeChainKitProvider.tsx` around lines 460 -
467, The update guard is being cleared synchronously before the async
i18n.changeLanguage completes; keep isUpdatingFromPropRef.current true until the
Promise resolves by moving the assignment into the Promise.finally handler: when
you set isUpdatingFromPropRef.current = true around i18n.changeLanguage(...) (in
the blocks that call i18n.changeLanguage and then possibly call
setCurrentLanguageState), chain .finally(() => { isUpdatingFromPropRef.current =
false; }) so the guard remains active until the language change completes; apply
this pattern to all occurrences that call i18n.changeLanguage (the block using
isUpdatingFromPropRef/currentLanguage/setCurrentLanguageState and the two other
locations noted).

@Agilulfo1820 Agilulfo1820 merged commit a9a6186 into main Mar 2, 2026
7 checks passed
@Agilulfo1820 Agilulfo1820 deleted the fix/languages branch March 2, 2026 15:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant