The return functions of
inlineTranslate
andinlinePlural
are parsed and replaced with translated texts in chunks sent to the browser at compile time
inlineTranslate
returns a functions to get the translation using key-value pairs:
const t = inlineTranslate();
t('title@@Qwik Speak')
Value after @@
is the optional default value:
`Qwik Speak`
t
function accept params as well:
t('greeting@@Hi! I am {{name}}', { name: 'Qwik Speak' })
name
param is replaced at runtime or during the inlining:
Hi! I am Qwik Speak
t
function accepts array of keys:
t(['value1@@Value 1', 'value2@@Value 2'])
and returns an array of translated values:
["Value 1", "Value 2"]
t
function can get arrays and objects directly from files:
{
"array": [
"one",
"two",
"three"
],
"obj": {
"one": "one",
"two": "two"
}
}
just pass to the function the type parameter:
import type { Translation } from 'qwik-speak';
t<string[]>('array')
t<Translation>('obj')
You can also access by array position:
t('array.2@@three')
Finally, it is possible to set arrays and objects passing a valid stringified default value:
t<string[]>('array@@["one","two","three"]')
t<Translation>('obj@@{"one":"one","two":"two"}')
You can have Html in translations, like:
{
"description": "<em>Internationalization (i18n) library to translate texts, dates and numbers in Qwik apps</em>"
}
but you have to use dangerouslySetInnerHTML
:
<p dangerouslySetInnerHTML={t('description')}></p>
On the client the text is inlined during build, so there are no XSS risks
inlinePlural
returns a functions that uses Intl.PluralRules API:
const p = inlinePlural();
p(1, 'devs')
When you run the extraction tool, it creates the Intl API plural rules for each language:
{
"devs": {
"one": "",
"other": ""
}
}
It is possible to set the default value passing a valid stringified json, keeping in mind that the counter is optionally interpolated with the value
parameter:
p(1, 'devs@@{"one": "{{ value }} software developer","other": "{{ value }} software developers"}')
Will result in:
{
"devs": {
"one": "{{ value }} software developer",
"other": "{{ value }} software developers"
}
}
It is rendered as:
1 software developer
When you use a translation like this:
const key = 'dynamic';
t(key)
you are using a dynamic translation. It means that it is not possible to evaluate the translation at compile time but only at runtime based on the value that the key takes on.
To instruct Qwik Speak to use dynamic translations, create a file with the values that these translations can take:
i18n/[lang]/runtime.json
{
"dynamic": "I'm a dynamic value"
}
and add the runtime
file to runtimeAssets
in configuration or useSpeak
provider.
QRL functions $
and lifecycle hooks like useTask$
create js chunks that will be lazy loaded. So you need to re-invoke inlineTranslate
inside them:
const fn$ = $(() => {
const t = inlineTranslate();
console.log(t('title@@Qwik Speak'));
});
inlineTranslate
and inlinePlural
work in component$
, Inline components, QRL and functions if called by the components, but they might not work in functions invoked on the server, such as routeLoader$
and endpoints.
Functions like routeLoader$
live on the server, which knows nothing about the context of the app, and depending on the case they can be invoked before the app runs. To translate on the server you need:
- make sure translations are available
- let the server know the current language of the user
server$
function can satisfy both conditions, since the function is executed only when invoked, and accepts parameters:
export const serverFn = server$(function (lang: string) {
const t = inlineTranslate();
return t('title', { name: 'Qwik Speak' }, lang);
});
export default component$(() => {
const locale = useSpeakLocale();
const s = useSignal('');
useTask$(async () => {
s.value = await serverFn(locale.lang)
});
return (<p>{s.value}</p>);
});
You can also extract the language directly into the function, through the request (cookies, params), instead of passing it as a parameter.
If you don't want to handle the keys inside the translation functions, but only the default values, you can enable automatic key generation:
- Extraction tool: add
--autoKeys=true
to the script - Inline Vite plugin: add
autoKeys: true
to the options
Note. You can enable this option, even if you use the syntax
key@@[default value]
.
If you enable this option, you can pass only the default values to the translation functions:
export default component$(() => {
const t = inlineTranslate();
const p = inlinePlural();
return (
<>
<h1>{t('app.title@@{{name}} demo', { name: 'Qwik Speak' })}</h1>
<h3>{t('New strings without existing keys')}</h3>
<p class="counter">{p(
1,
'{"one": "{{ value }} {{ color }} zebra","other": "{{ value }} {{ color }} zebras"}',
{
color: t('black and white')
}
)}</p>
</>
);
});
If you run the extractor, you will get json files like this:
{
"app": {
"title": "Qwik Speak demo"
},
"autoKey_3c909eb27a10640be9495cff142f601c": {
"one": "{{ value }} {{ color }} zebra",
"other": "{{ value }} {{ color }} zebras"
},
"autoKey_8e4c0598319b3b04541df2fc36cb6fc5": "New strings without existing keys",
"autoKey_cbe370e60f10f92d4dd8b3e9c267b1fa": "black and white"
}
Then the Inline plugin will manage the self-assigned keys.
useFormatDate
returns a functions that uses Intl.DateTimeFormat API to format dates:
const fd = useFormatDate();
fd(Date.now(), { dateStyle: 'full', timeStyle: 'short' })
The second param in the signature is an Intl DateTimeFormatOptions
object, which allows you to customize the format:
Monday, March 6, 2023 at 12:20 PM
Optionally it uses the time zone set in timeZone
property of the SpeakLocale
.
useRelativeTime
returns a functions that uses Intl.RelativeTimeFormat API to format relative times:
const rt = useRelativeTime();
rt(-1, 'second')
The second param in the signature is an Intl RelativeTimeFormatUnit
string:
1 second ago
useFormatNumber
returns a functions that uses Intl.NumberFormat API to format numbers:
const fn = useFormatNumber();
fn(1000000)
1,000,000
To format as currency, you have to set the style
property of the second param, an Intl NumberFormatOptions
object:
fn(1000000, { style: 'currency' })
$1,000,000.00
It uses the currency code set in currency
property of the SpeakLocale
.
To format as unit, you have to set the style
and unit
properties of the second param:
const locale = useSpeakLocale();
const units = locale.units!;
fn(1, { style: 'unit', unit: units['length'] })
1 mi
It uses the unit set in optional units
property of the SpeakLocale
:
units: { 'length': 'mile' }
useDisplayName
returns a functions that uses Intl.DisplayNames API to translate language, region, script or currency display names:
const dn = useDisplayName();
dn('en-US', { type: 'language' })
American English
The locale used by
useFormatDate
,useRelativeTime
,useFormatNumber
anduseDisplayName
is primarily theextension
property of theSpeakLocale
if provided, otherwise thelang
property.extension
is the language with Intl extensions, in the formatlanguage[-script][-region][-extensions]
likeen-US-u-ca-gregory-nu-latn
Each of the translation and localization functions accepts a different language other than the current one as its last argument:
const t = inlineTranslate();
t('title@@Qwik Speak', undefined, 'it-IT')
For the translation to occur in the language passed as an argument, you need to set the additional language to useQwikSpeak
or useSpeak
providers:
useQwikSpeak({ config, translationFn, langs: ['it-IT'] });