Closed cohapzp closed 11 months ago
en/index.js
export default {
dates: {
monthsNames: {
'0': 'January',
'1': 'February',
'2': 'March',
'3': 'April',
'4': 'May',
'5': 'June',
'6': 'July',
'7': 'August',
'8': 'September',
'9': 'October',
'10': 'November',
'11': 'December',
}
}
}
Your component
function Comp() {
const t = useT();
const months = new Array(12)
.fill(0)
.map((_, i) => t(`dates.monthsNames.${i}` as 'dates.monthsNames.0'));
// should print out January
return <p>{months[0]}</p>
}
@lindesvard's solution seems great. What's your use case?
@lindesvard's solution seems great. What's your use case?
Thanks @lindesvard , I will dig into that code, need to expand my knowledge a little bit to understand that.
@QuiiBz , what I want to achieve is to get data from fetch response(I can get three language variation from it), populate dedicated dictionaries and then use them in the app. I've managed to get, populate and use them, but in kinda limited way.
What I schematically got from response:
{
"0": {
"url": "/services",
"title": "Services"
},
"1": {
"url": "/aboutus",
"title": "About us"
},
"2": {
"url": "/contacts",
"title": "Contacts"
}
}
And how dictionary looks in this case:
import { getMenuItems } from "../../utilities/apiHelper";
const getEngMenu = await getMenuItems("/?lc=en");
export default {
translations: {
header: {
menu: getEngMenu,
},
},
} as const;
So this is a menu which is should be looped through in order to show it on the page and I am trying to figure it out.
In the component I can access it via something like:
{t("translations.header.menu.0.title")}
Where the "title" goes from Type described for that kind of promise and because of that can be accessible to reference(no TypeScript error). But, obviously, hardcoded indexes are not the approach I am looking for.
Sorry for maybe stupid explanations/questions and thank you for your time and response :)
I'm not sure how we could have a better API for this. One thing that comes to my mind is that getMenuItems
should be called outside of the locales file, which should only contain direct translations:
export default {
translations: {
header: {
menu: {
services: "Services",
aboutus: "About us",
contactus: "Contact us",
},
},
},
} as const;
async function ServerComponent() {
const menuItems = await getMenuItems(); // e.g. being an array of services, aboutus, contacts
const t = await getI18n();
menuItems.forEach(menuItem => {
t(`translations.header.menu.${menuItem}`)
});
}
However I don't know if that's something you can achieve easily in your application, but it makes more sense this way.
@QuiiBz works like a charm even with my data structure! But with few minor changes - .forEach returns void, so I've used .map instead:
{Object.keys(menuItemsArray).map(menuItem => {
return <p>{t(`translations.header.menu.${menuItem}.title`)}</p>;
})}
Plus TS shows warning expecting second parameter here but works as well:
As for API - another package can output object instead of string using this kind of parameter: const translations = t("translations", { returnObjects: true }); --> work with "translations" like with object. Maybe it would be handy in these scenarios...
Yeah the forEach
was just an example. The TS error might be because the type of menuItem
in the loop is string
, instead of being narrowed down to 'services' | 'aboutus' | 'contactus'
. You could manually cast it:
${menuItem as 'services' | 'aboutus' | 'contactus'}
As for the API, this seems a bit out-of-scope for next-international. It feels too specific to be included by default: most users won't need it, and you can "easily" achieve it yourself like you did. I'll close the issue for now but feel free to add more arguments if you believe it should be added.
Hello!
I am sorry if this topic was touched but I haven't found any solution in the docs and here. The issue is I want to iterate through translation object to render a list of strings under the certain object key.
Is it possible?
Thanks.