Closed heejinp closed 6 months ago
Hey, yeah I'll update the exmple app, I think the issue might be in different syntax for empty namespace.
Should be something like this:
export async function getStaticData(
languages: string[],
namespaces: string[] = ['']
) {
const result: Record<string, any> = {};
for (const lang of languages) {
for (const namespace of namespaces) {
if (namespace) {
result[`${lang}:${namespace}`] = (
await import(`../i18n/${namespace}/${lang}.json`)
).default;
} else {
result[lang] = (await import(`../i18n/${lang}.json`)).default;
}
}
}
return result;
}
Should be something like this:
export async function getStaticData( languages: string[], namespaces: string[] = [''] ) { const result: Record<string, any> = {}; for (const lang of languages) { for (const namespace of namespaces) { if (namespace) { result[`${lang}:${namespace}`] = ( await import(`../i18n/${namespace}/${lang}.json`) ).default; } else { result[lang] = (await import(`../i18n/${lang}.json`)).default; } } } return result; }
yup I thought it might be the syntax thing too, so tried your snippet and still getting the fallback text. before that, it seems like the namespace is partially working out in CSR like this:
I'll be waiting for the update! thanks
Hmm, could you elaborate more? I think there must be some other problem, do you have it correctly connected to some project in Tolgee, with appropriate strings?
Hmm, could you elaborate more? I think there must be some other problem, do you have it correctly connected to some project in Tolgee, with appropriate strings?
Okay, I am testing in the demo app and translation works fine without namespace but:
/test
and /common
under i18n
and put json files inside of both subfoldersgetStaticData
function as same as your code, it starts showing the object key as translation not the valueThe result object of getStaticData
is like:
{
'en:test': {
'add-item-add-button': 'Add',
'add-item-input-placeholder': 'New list item',
'app-title': 'What To Pack',
'delete-item-button': 'Delete',
'menu-item-translation-methods': 'Translation methods',
'send-via-email': 'Send via e-mail',
'share-button': 'Share',
this_is_a_key: 'This is a key',
this_is_a_key_with_params: 'This is key with params {key} {key2}',
this_is_a_key_with_tags: 'This is a key with tags <b>bold</b> <b><i>{key}</i></b>'
},
'fr:test': {
'add-item-add-button': 'Ajouter',
'add-item-input-placeholder': 'Nouveau élément de la liste',
'app-title': 'Quoi emballer',
'delete-item-button': 'Supprimer',
'menu-item-translation-methods': 'Méthodes de la traduction',
'send-via-email': 'Envoyer par e-mail',
'share-button': 'Partager',
this_is_a_key: "C'est un clé",
this_is_a_key_with_params: "C'est la clé avec paramètres {key} {key2}",
this_is_a_key_with_tags: "C'est la clé avec des tags <b>bold</b> <b><i>{key}</i></b>"
},
'en:common': {
'add-item-add-button': 'Add',
'add-item-input-placeholder': 'New list item',
'app-title': 'What To Pack',
'delete-item-button': 'Delete',
'menu-item-translation-methods': 'Translation methods',
'send-via-email': 'Send via e-mail',
'share-button': 'Share',
this_is_a_key: 'This is a key',
this_is_a_key_with_params: 'This is key with params {key} {key2}',
this_is_a_key_with_tags: 'This is a key with tags <b>bold</b> <b><i>{key}</i></b>'
},
..... and more ...
}
These are the only changes I made, and no error was thrown from the await import()
syntax but I think both issues are coming from this part.
Could you also share tolgee configuration and how you use it in the code?
Could you also share tolgee configuration and how you use it in the code?
client.tsx
'use client';
import { TolgeeBase } from './shared';
import { TolgeeProvider, useTolgeeSSR } from '@tolgee/react';
import { useRouter } from 'next/navigation';
import { useEffect } from 'react';
type Props = {
locales: any;
locale: string;
children: React.ReactNode;
};
const tolgee = TolgeeBase().init();
export const TolgeeNextProvider = ({ locale, locales, children }: Props) => {
const tolgeeSSR = useTolgeeSSR(tolgee, locale, locales);
const router = useRouter();
useEffect(() => {
const { unsubscribe } = tolgeeSSR.on('permanentChange', () => {
router.refresh();
});
return () => unsubscribe();
}, [tolgeeSSR, router]);
return (
<TolgeeProvider
tolgee={tolgeeSSR}
options={{ useSuspense: false }}
fallback="Loading"
>
{children}
</TolgeeProvider>
);
};
server.tsx
import { useLocale } from 'next-intl';
import { TolgeeBase, ALL_LOCALES, getStaticData } from './shared';
import { createServerInstance } from '@tolgee/react/server';
export const { getTolgee, getTranslate, T } = createServerInstance({
getLocale: useLocale,
createTolgee: async (locale) =>
TolgeeBase().init({
staticData: await getStaticData(ALL_LOCALES),
observerOptions: {
fullKeyEncode: true,
},
language: locale,
fetch: async (input, init) => {
const data = await fetch(input, { ...init, next: { revalidate: 0 } });
return data;
},
}),
});
shared.tsx
import { FormatIcu } from "@tolgee/format-icu";
import { DevTools, Tolgee } from "@tolgee/web";
const apiKey = process.env.NEXT_PUBLIC_TOLGEE_API_KEY;
const apiUrl = process.env.NEXT_PUBLIC_TOLGEE_API_URL;
export const ALL_LOCALES = ["en", "cs", "de", "fr"];
export const DEFAULT_LOCALE = "en";
export async function getStaticData(
languages: string[],
namespaces: string[] = ["test", "common"]
) {
const result: Record<string, any> = {};
for (const namespace of namespaces) {
for (const lang of languages) {
if (namespace) {
result[`${lang}:${namespace}`] = (
await import(`../i18n/${namespace}/${lang}.json`).catch((error) => {
console.log(error);
})
).default;
} else {
result[lang] = (
await import(`../i18n/${lang}.json`).catch((error) => {
console.log(error);
})
).default;
}
}
}
console.log(result);
return result;
}
export function TolgeeBase() {
return Tolgee().use(FormatIcu()).use(DevTools()).updateDefaults({
apiKey,
apiUrl,
fallbackLanguage: "en",
});
}
about middleware.ts
, navigation.ts
files,
and the rest of the components/pages I didn't touch them at all from the demo.
Ok, I think everything is correct, except, you are not telling Tolgee to use the namespaces that you've provided.
// in shared.ts
export function TolgeeBase() {
return Tolgee()
.use(FormatIcu())
.use(DevTools())
.updateDefaults({
apiKey,
apiUrl,
fallbackLanguage: 'en',
defaultNs: 'test', // <– this tells Tolgee that this is a default namespace, if not specified
ns: ['test', 'common'], // <- this says what namespaces should be available after start, important for DevTools
});
}
Then if you want to use test
namespace you can just call t
function without the namespace definition.
For common
namespace, use t('key_name', { ns: 'common' })
.
Ok, I think everything is correct, except, you are not telling Tolgee to use the namespaces that you've provided.
// in shared.ts export function TolgeeBase() { return Tolgee() .use(FormatIcu()) .use(DevTools()) .updateDefaults({ apiKey, apiUrl, fallbackLanguage: 'en', defaultNs: 'test', // <– this tells Tolgee that this is a default namespace, if not specified ns: ['test', 'common'], // <- this says what namespaces should be available after start, important for DevTools }); }
Then if you want to use
test
namespace you can just callt
function without the namespace definition. Forcommon
namespace, uset('key_name', { ns: 'common' })
.
Ahh you're right 🤦
After adding defaultNS
and ns
it started working with correct translations / in js disabled mode in every languages.
Thanks a lot!
Hi,
When I modify
getStaticData
function inshared.ts
file like this:it shows a blank page in the JavaScript disabled mode, otherwise(enable js or not using namespace) it works. Do the docs(https://tolgee.io/js-sdk/integrations/react/next/app-router) cover the case for using a namespace too?
dependencies: