Trying to use this
<Text>
{I18n.t('login_condition', {
appName: <Text style={{color: 'blue'}} onPress={() => Linking.openURL('http://google.com')}>Google</Text>
})}
</Text>
I'm sorry but I'm not able to understand what you are trying to achieve, can you provide some more info?
Values interpolation should work exactly like in i18n-js.
Sure. basically I have some text needed for translation "By using Application you accept the privacy politics and our terms of use." where privacy politics is the link or text with different styles.
I want to avoid splitting the text into multiple parts:
I want to translate the whole phrase like this
'login_condition': 'By using %{appName} you accept the %{privacyLink} and our %{termLink}',
and can't find the way to do it.
Correct me if I am mistaken but you're trying to interpolate React Component (not simple object/text) because you need to style a portion of text, am I right?
Unfortunately this is out of the scope of this library.
Basically you can interpolate text in this way:
// Translation definition:
WELCOME_MSG: 'Hello {{name}}!'
// In you component:
I18n.t('WELCOME_MSG', { name: 'Alexander' })
But you can't style Alexander differently from the rest of the text, you must create your own function/wrapper to do so... 馃檷
Closing, let me know if you find any cool solution to your issue!
@mmazzarolo can you guide in writing the wrapper
i am facing same issue and just make a quick solution:
create a function that return array of react components
const tWithComponent = (i18nKey, components, t) => {
let string = t(i18nKey)
let results = []
components.forEach((component, idx) => {
let splitedStrings = string.split('{' + idx + '}')
results.push(splitedStrings[0])
results.push(component)
string = splitedStrings[1]
})
results.push(string)
return results
}
return (
...
{tWithComponent('doNotHaveAccountYet', [<Link key='0' to='/signup'>{t('signUp')}</Link>], t)}
...
)
i18n string will look like:
"doNotHaveAccountYet": "Do not have account yet? Click {0} to start!"
@TONYHOKAN - what is t?
@compojoom
i am using react-i18next and t is the function passed by I18n component to child function and triggers loading the translation files needed. I think the t is equal to I18n.t().
@TONYHOKAN thanks! Why are you passing t as parameter to the function?
I rewrote it to:
export const tWithComponent = (i18nKey, components) => {
let string = I18n.t(i18nKey)
let results = []
components.forEach((component, idx) => {
let splitedStrings = string.split('{' + idx + '}')
results.push(splitedStrings[0])
results.push(component)
string = splitedStrings[1]
})
results.push(string)
return results
}
and it works! Thanks again :)
@compojoom as i was using react-i18next HOC to wrap the parent component of tWithComponent and could not directly access t via global context. Your are right that we do not no need to pass t as parameter if you can access t function in global context.
I came up with a helper component that does the 'rich text interpolation'. It's written in ES5, and without semi-colon (airbnb rules).
import React from 'react'
import PropTypes from 'prop-types'
import { Text } from 'react-native'
import I18n from 'react-native-i18n'
export const RichI18n = (props) => {
const { id, values, baseComponent, baseComponentStyle, baseComponentProps, ...other } = props
// get the translations interpoling the placeholder by itself
const keys = Object.keys(values)
const placeHolders = {}
keys.forEach((key) => placeHolders[key] = `{{${key}}}`)
const translation = I18n.t(id, { ...(other || {}), ...placeHolders }) || ''
// split the translated string, using default i18n-js regex, odd indexes will correlate to a key to be interpolated
// https://github.com/fnando/i18n-js/blob/master/app/assets/javascripts/i18n.js
const splitted = translation.split(/(?:\{\{|%\{)(.*?)(?:\}\}?)/gm)
const interpolated = []
splitted.forEach((str, idx) => {
if ((idx % 2) === 0) {
interpolated.push(str)
} else {
const child = values[str]
if (typeof child === 'string') {
interpolated.push(child)
} else {
interpolated.push(React.cloneElement(child, { key: idx }))
}
}
})
const BaseComponent = baseComponent
return (
<BaseComponent style={baseComponentStyle} {...baseComponentProps}>{interpolated}</BaseComponent>
)
}
RichI18n.propTypes = {
id: PropTypes.string.isRequired,
values: PropTypes.object,
baseComponent: PropTypes.any,
baseComponentStyle: PropTypes.object,
baseComponentProps: PropTypes.object
}
RichI18n.defaultProps = {
values: {},
baseComponent: Text,
baseComponentStyle: {},
baseComponentProps: {}
}
Usage:
<RichI18n
id="my.interpolation.test"
defaultValue="This is an {{interpolation}} test {{plain}} where {{you}} can repeat {{interpolation}} variables {{translated}}"
values={{
interpolation: <Text style={{ fontWeight: 'bold' }}>bold</Text>,
you: <Text style={{ color: 'red' }}>me</Text>,
plain: 'Just plain text',
translated: I18n.t('Translated text', { defaultValue: 'Translated text' })
}}
/>
Most helpful comment
I came up with a helper component that does the 'rich text interpolation'. It's written in ES5, and without semi-colon (airbnb rules).
Usage: