|
1 | 1 | "use client";
|
2 | 2 |
|
3 |
| -import React, { useEffect, useState } from "react"; |
| 3 | +import React, { useEffect, useState, useCallback } from "react"; |
4 | 4 | import defaultTranslations from "@/i18n/translations.en.json";
|
5 | 5 |
|
6 | 6 | const languages = {
|
@@ -58,82 +58,58 @@ const getNestedTranslation = (
|
58 | 58 | break;
|
59 | 59 | }
|
60 | 60 | }
|
61 |
| - if (typeof acc === "string") { |
62 |
| - return acc; |
63 |
| - } |
64 |
| - return undefined; |
| 61 | + return typeof acc === "string" ? acc : undefined; |
65 | 62 | };
|
66 | 63 |
|
67 |
| -async function translate(translationKey: string) { |
68 |
| - const language = await getAvailableLanguage(); |
69 |
| - |
70 |
| - // Helper function to load translations |
71 |
| - const loadTranslations = async (lang: string) => { |
72 |
| - try { |
73 |
| - return await import(`@/i18n/translations.${lang}.json`); |
74 |
| - } catch { |
75 |
| - console.warn(`Translation file for language "${lang}" not found.`); |
76 |
| - return null; |
77 |
| - } |
78 |
| - }; |
79 |
| - |
80 |
| - // Load translations for the selected language and the default language |
81 |
| - const translations = await loadTranslations(language); |
82 |
| - |
83 |
| - // Attempt to get the translation in the selected language, then fall back to default |
84 |
| - const translation = |
85 |
| - getNestedTranslation(translations, translationKey) || |
86 |
| - getNestedTranslation(defaultTranslations, translationKey); |
87 |
| - |
88 |
| - // Render the translation if found; otherwise, return the key |
89 |
| - return translation || translationKey; |
| 64 | +async function fetchTranslations(lang: string) { |
| 65 | + try { |
| 66 | + const translations = await import(`@/i18n/translations.${lang}.json`); |
| 67 | + return translations; |
| 68 | + } catch { |
| 69 | + console.warn(`Translation file for language "${lang}" not found.`); |
| 70 | + return null; |
| 71 | + } |
90 | 72 | }
|
91 | 73 |
|
92 |
| -export const t = (translationKey: string): string => { |
93 |
| - const defaultTranslation = |
94 |
| - getNestedTranslation(defaultTranslations, translationKey) || translationKey; |
95 |
| - const [translation, setTranslation] = useState(defaultTranslation); |
96 |
| - |
97 |
| - const updateTranslation = async () => { |
98 |
| - const translatedText = await translate(translationKey); |
99 |
| - setTranslation(translatedText); |
100 |
| - }; |
| 74 | +export function useTranslation() { |
| 75 | + const [translations, setTranslations] = |
| 76 | + useState<TranslationObject>(defaultTranslations); |
101 | 77 |
|
102 | 78 | useEffect(() => {
|
103 |
| - // Initial translation update |
104 |
| - updateTranslation(); |
105 |
| - |
106 |
| - // Update translation when the language in localStorage changes from other browsing context |
107 |
| - const handleStorageChange = (event: StorageEvent) => { |
108 |
| - if (event.key === "next-export-i18n-lang") { |
109 |
| - updateTranslation(); |
110 |
| - } |
| 79 | + const fetchLanguageAndTranslations = async () => { |
| 80 | + const lang = await getAvailableLanguage(); |
| 81 | + const loadedTranslations = await fetchTranslations(lang); |
| 82 | + setTranslations(loadedTranslations || defaultTranslations); |
111 | 83 | };
|
112 | 84 |
|
113 |
| - // Update translation when the language in localStorage changes from current browsing context |
114 |
| - const handleLocalStorageLangChange = () => { |
115 |
| - updateTranslation(); |
116 |
| - }; |
| 85 | + fetchLanguageAndTranslations(); |
| 86 | + |
| 87 | + const handleLocalStorageLangChange = () => fetchLanguageAndTranslations(); |
117 | 88 |
|
118 |
| - // Listen for localStorage changes |
119 |
| - window.addEventListener("storage", handleStorageChange); |
120 | 89 | window.addEventListener(
|
121 | 90 | "localStorageLangChange",
|
122 | 91 | handleLocalStorageLangChange,
|
123 | 92 | );
|
124 |
| - |
125 |
| - // Clean up listener on component unmount |
126 |
| - return () => { |
127 |
| - window.removeEventListener("storage", handleStorageChange); |
| 93 | + return () => |
128 | 94 | window.removeEventListener(
|
129 | 95 | "localStorageLangChange",
|
130 | 96 | handleLocalStorageLangChange,
|
131 | 97 | );
|
132 |
| - }; |
133 |
| - }, [translationKey]); |
| 98 | + }, []); |
134 | 99 |
|
135 |
| - return translation; |
136 |
| -}; |
| 100 | + const t = useCallback( |
| 101 | + (translationKey: string): string => { |
| 102 | + return ( |
| 103 | + getNestedTranslation(translations, translationKey) || |
| 104 | + getNestedTranslation(defaultTranslations, translationKey) || |
| 105 | + translationKey |
| 106 | + ); |
| 107 | + }, |
| 108 | + [translations], |
| 109 | + ); |
| 110 | + |
| 111 | + return { t }; |
| 112 | +} |
137 | 113 |
|
138 | 114 | export const LanguageSelector: React.FC<LanguageSelectorProps> = ({
|
139 | 115 | className,
|
|
0 commit comments