Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to translate items in an array of objects with i18n #645

Closed
JavierPons opened this issue Dec 14, 2018 · 14 comments
Closed

How to translate items in an array of objects with i18n #645

JavierPons opened this issue Dec 14, 2018 · 14 comments

Comments

@JavierPons
Copy link

First of all thank you for react-i18next, its a big work, very useful and as well for the fast answer yesterday. Till now I have been enjoying react-i18n translating an app into three different language. It works very well.
But I have an issue here with translate an array of objects. The problem is how to use and {t('')} if I want to translate the item CONTENT of object in the array.
What it would be easy and nice way to do it? Content is what it is seen at the front page menu. I want translate it.
I have my translate.json file with the translation.
"en": { "translation": { "frontpage":{ "home": "home", "price": "price" and so on.... } } }

`
imports here......

const mapStateToProps = (state, ownProps) => {
return {
navItems: navItems,
path: ownProps.location.pathname
}
}

const mapDispatchToProps = dispatch => {
return {
dispatch
}
}

const mergeProps = ( stateProps, dispatchProps, ownProps ) => Object.assign( {}, stateProps, dispatchProps, ownProps)

const FrontMainContainer = connect(mapStateToProps, mapDispatchToProps, mergeProps)(FrontMainComponent)

const navItems = [
{
name: 'home',
content: 'HOME',
url: '/home/home'
},
{
name: 'list-alt',
content: 'PRICE',
url: '/home/price'
},
{
name: 'info-circle',
content: 'QUESTIONS',
url: '/home/faq'
},
{
name: 'users',
content: 'SOMETHING A',
url: '/home/somethinga'
},
{
name: 'envelope',
content: 'SOMETHING B',
url: '/home/somethingb'
}
]

export default FrontMainContainer
`

@jamuhl
Copy link
Member

jamuhl commented Dec 14, 2018

It depends:

If you're adding translations on init (options.resources) and therefore have no async loading of them you just can content: i18n.t('theKey.needed') (and import the i18n file) -> change language won't work because that value gets set once -> so better do:

if using a backend and loading translations (or need to change language on runtime) you will need to find a way to translate on runtime -> not use content but render your text during render methods

@jamuhl jamuhl closed this as completed Dec 15, 2018
@JavierPons
Copy link
Author

The issue is solve. Now is working and translating very well. Thank you for your support and work.

@jamuhl
Copy link
Member

jamuhl commented Dec 19, 2018

If you like this module don’t forget to star this repo. Make a tweet, share the word or have a look at our https://locize.com to support the devs of this project -> there are many ways to help this project 🙏

@shreyanshjain14
Copy link

@JavierPons can elaborate more how you resolved this issue??

@jamuhl
Copy link
Member

jamuhl commented May 17, 2023

@shreyanshjain14 eg. like #1236 (comment) or #1306 (comment) or #909 (comment)

endless existing issues discussing this

@shreyanshjain14
Copy link

shreyanshjain14 commented May 17, 2023

@jamuhl thanks for the help

i have below TS function

import i18n from "../../i18n/config";

abc(setting: SecuritySetting, psVersion: string) {

  const key: string = PageKey.getPageKeyFromApp(setting.path);
  return (
     <>
        <a onClick={() => this.enableModifyPageAccess(key, psVersion)}>{i18n.t(`${setting.description}`)}</a>
        {setting.info && (
           <Tooltip title={<Typography component="p">{setting.info}</Typography>}>
              <InfoOutlined className={"ld-inline-icon"} fontSize={"small"} />
           </Tooltip>
        )}
     </>
  );

}

{i18n.t(${setting.description})} is not getting changed when i change the language....could you please help me out on this

@shreyanshjain14
Copy link

shreyanshjain14 commented May 17, 2023

@jamuhl

const myExport = {};

function fill() {
myExport.foo = i18n.t('foo');
}

// run it initial
fill();

// bind some events and fill values again (doing the magic you expect to happen magically)
i18n.on('languageChanged init',() => {
fill(); // fills myExport with new value for foo based on current i18n lng
});

if i willl do something like this than i have to maintain many key value pairs in myExport = {}; object

i will render the something like
{myexport.foo}???

@jamuhl
Copy link
Member

jamuhl commented May 17, 2023

@shreyanshjain14 components will need somewhere an useTranslation or alternative to trigger rerenders....calling i18n.t is just calling a function (where should the magic happen?!?)

the rest is average programmer skills (understanding that t returns a string and not more - so update must be handled by user using i18n.on)

@shreyanshjain14
Copy link

@jamuhl actually the issue is the function abc is residing inside a class, so can not use the usetranslation hook here

@jamuhl
Copy link
Member

jamuhl commented May 17, 2023

still....either your function is called during rendering or not...if not use the i18n.on to listen to events needing a rerun of that function

but like written everywhere...simplest is to move translation closer to UI rendering...eg. by letting those functions you use build a key -> than use that key to get correct translation during rendering.

@shreyanshjain14
Copy link

@jamuhl

here is the code, have a look

class abc {
translatedData: Object = {}
getModifyPageAccessComponent(setting: SecuritySetting, psVersion: string) {

  const key: string = PageKey.getPageKeyFromApp(setting.path);

  function fill() {
     this.translatedData[`${setting.description}`] = i18n.t(`${setting.description}`)
     //setting.description = i18n.t(`${setting.description}`);
     console.log(this.translatedData, "hello")

  }

  // run it initial
  fill();

  // bind some events and fill values again (doing the magic you expect to happen magically)
  i18n.on('languageChanged', () => {
     fill(); // fills myExport with new value for foo based on current i18n lng
  });
  console.log(this.translatedData[`${setting.description}`], "dfh")
  return (
     <>
        <a onClick={() => this.enableModifyPageAccess(key, psVersion)}>{this.translatedData[`${setting.description}`]}</a>
        {setting.info && (
           <Tooltip title={<Typography component="p">{setting.info}</Typography>}>
              <InfoOutlined className={"ld-inline-icon"} fontSize={"small"} />
           </Tooltip>
        )}
     </>
  );

}
}

so im maintainig the translated data object here, but still the data is not getting chnaged

@jamuhl
Copy link
Member

jamuhl commented May 17, 2023

your code is a component...

-> i18n.on ---> use on non-components
-> useTranslation ---> use on components

@shreyanshjain14
Copy link

shreyanshjain14 commented May 17, 2023

@jamuhl
as this component is wrapped inside the class im getting this error:
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:

  1. You might have mismatching versions of React and the renderer (such as React DOM)
  2. You might be breaking the Rules of Hooks
  3. You might have more than one copy of React in the same app
    See https://fb.me/react-invalid-hook-call for tips about how to debug and fix this problem.

@jamuhl
Copy link
Member

jamuhl commented May 17, 2023

class components can't use hooks...useTranslation has alternatives like the HOC for such cases...https://react.i18next.com/latest/withtranslation-hoc

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

No branches or pull requests

3 participants