|
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