# @soleil-se/i18n

Utility to create translations for an app.\
Language is determined automatically using `@sitevision/api/common/app` and its property `locale`.

> **Note**
>
> `@sitevision/api/common/app` is not available in a configuration context, use the translation utils in [@soleil-se/config-svelte](/packages/config-svelte/#i18n) instead.

## Prerequisites

* `@soleil-se/build-app@^1.0.0` or `@sitevision/sitevision-scripts@^3.0.0`.
* WebApps 2 enabled app.

## Install

```sh
npm i @soleil-se/i18n
```

## Example

For simpler translations you can put them in a single file.

**i18n.js**

```js
import { createI18n } from '@soleil-se/i18n';


const i18n = createI18n({
  en: {
    hello: 'Hello'
  },
  sv: {
    hello: 'Hej'
  },
});


export default i18n;
```

But it’s also possible to split them up in different files.

**i18n.js**

```js
import { createI18n } from '@soleil-se/i18n';


import en from './en';
import sv from './sv';


const i18n = createI18n({ en, sv });


export default i18n;
```

Before 2.4.0**

**i18n.js**

```javascript
import { addMessages, translate } from '@soleil-se/i18n';


import en from './en';
import sv from './sv';


addMessages('en', en);
addMessages('sv', sv);


export default translate;
```

**en.js**

```javascript
export default {
  hello: 'Hello',
};
```

**sv.js**

```javascript
export default {
  hello: 'Hej',
};
```

Then import the i18n.js file where you need to translate.

**index.js**

```js
import i18n from './i18n';


console.log(i18n('hello'));
```

**Component.svelte**

```svelte
<script>
  import i18n from './i18n';
</script>


<h1>{i18n('hello')}</h1>
```

### RESTApp Since 2.5.2

In a RESTApp you can’t determine the locale so you need to set it manually in your route.\
Will fall back to `en` if locale cannot be determined.

**index.js**

```js
import router from '@sitevision/api/common/router';
import { setLocale } from '@soleil-se/i18n';


import i18n from './i18n';


router.get('/sv', (req, res) => {
  setLocale('sv');
  res.json({
    hello: i18n('hello'),
  });
});


router.get('/en', (req, res) => {
  setLocale('en');
  res.json({
    hello: i18n('hello'),
  });
});
```

## API

### createI18n(\[messages])

This function creates a new i18n instance.

| Param       | Type     | Default | Description       |
| ----------- | -------- | ------- | ----------------- |
| \[messages] | `object` | `{}`    | Initial messages. |

**Returns**: `i18n` - i18n instance.

Add messages when creating a new instance.

**i18n.js**

```js
import { createI18n } from '@soleil-se/i18n';


const i18n = createI18n({
  en: {
    hello: 'Hello'
  },
  sv: {
    hello: 'Hej'
  },
});


export default i18n;
```

**i18n.js**

```js
import { createI18n } from '@soleil-se/i18n';


const i18n = createI18n({
  en: {
    hello: 'Hello {name}!'
  },
  sv: {
    hello: 'Hej {name}!'
  },
});


export default i18n;
```

#### i18n(path, \[values]) ⇨ `string`

Translate a message.

**Returns**: `string` - Translated message.

| Param     | Type     | Default | Description                  |
| --------- | -------- | ------- | ---------------------------- |
| path      | `string` |         | Path to message key.         |
| \[values] | `object` | `{}`    | Values to inject in message. |

**index.js**

```js
import i18n from './i18n';
console.log(i18n('hello')); // Hej
```

**index.js**

```js
import i18n from './i18n';
console.log(i18n('hello', { name: 'Foo' })); // Hej Foo!
```

#### i18n.addMessages(locale, messages)

Add a locale with messages.

| Param    | Type     | Description      |
| -------- | -------- | ---------------- |
| locale   | `string` | Locale key.      |
| messages | `Object` | Messages object. |

**i18n.js**

```js
import { createI18n } from '@soleil-se/i18n';


const i18n = createI18n();


i18n.addMessages('en', { hello: 'Hello' });
i18n.addMessages('sv', { hello: 'Hej' });


return i18n;
```

Is also chainable.

**i18n.js**

```js
import { createI18n } from '@soleil-se/i18n';


const i18n = createI18n()
  .addMessages('en', { hello: 'Hello' })
  .addMessages('sv', { hello: 'Hej' });


export default i18n;
```

#### i18n.setMessages(messages)

Sets all messages.

| Param    | Type     | Description                                    |
| -------- | -------- | ---------------------------------------------- |
| messages | `Object` | Messages object with locale keys at top level. |

```js
import { createI18n } from '@soleil-se/i18n';


const i18n = createI18n();


i18n.setMessages({
  en: { hello: 'Hello' },
  sv: { hello: 'Hej'},
});


return i18n;
```

#### i18n.getMessages()

Get all messages for current locale as an object.

**i18n.js**

```js
import { createI18n } from '@soleil-se/i18n';


const i18n = createI18n({
  en: { hello: 'Hello' },
  sv: { hello: 'Hej' },
});


export default i18n;
```

**index.js**

```js
import i18n from './i18n';


console.log(i18n.getMessages());
```

#### i18n.messageExists(path)

Check if a translation for a message exists or not for the current locale.

**Returns**: `boolean` - If translation of message exists or not.

| Param | Type     | Description          |
| ----- | -------- | -------------------- |
| path  | `string` | Path to message key. |

**i18n.js**

```js
import { createI18n } from '@soleil-se/i18n';


const i18n = createI18n({
  en: { hello: 'Hello' },
  sv: { hello: 'Hej' },
});


export default i18n;
```

**index.js**

```js
import i18n from './i18n';


console.log(i18n.messageExists('hello'));
```

#### i18n.translate(path, \[values]) ⇨ `string`

> **Deprecated**
>
> Use [i18n](#i18npath-values--string) instead.

Translate a message.

**Returns**: `string` - Translated message.

| Param     | Type     | Default | Description                  |
| --------- | -------- | ------- | ---------------------------- |
| path      | `string` |         | Path to message key.         |
| \[values] | `object` | `{}`    | Values to inject in message. |

**index.js**

```js
import i18n from './i18n';
console.log(i18n.translate('hello')); // Hej
```

**index.js**

```js
import i18n from './i18n';
console.log(i18n.translate('hello', { name: 'Foo' })); // Hej Foo!
```

### setLocale(locale)

Set locale to be used when translating

| Param  | Type  | Description                                       |
| ------ | ----- | ------------------------------------------------- |
| locale | `any` | Can be anything that resolves to a locale string. |

```js
import { setLocale } from '@soleil-se/i18n';


setLocale('sv');
```

### getLocale() ⇨ `string`

Get current locale as string.

**Returns**: `string` - Current locale.

```js
import { getLocale } from '@soleil-se/i18n';


if(getLocale() === 'sv') {
  console.log('Här vare svenskt!');
}
```

### addMessages(locale, messages)

> **Deprecated**
>
> Use [i18n.addMessages](#i18naddmessageslocale-messages) instead.

Add a locale with messages.

| Param    | Type     | Description      |
| -------- | -------- | ---------------- |
| locale   | `string` | Locale key.      |
| messages | `Object` | Messages object. |

```js
import { addMessages } from '@soleil-se/i18n';


addMessages('en', { hello: 'Hello'});
addMessages('sv', { hello: 'Hej'});
```

### setMessages(messages)

> **Deprecated**
>
> Use [i18n.setMessages](#i18nsetmessagesmessages) instead.

Sets all messages.

| Param    | Type     | Description                                    |
| -------- | -------- | ---------------------------------------------- |
| messages | `Object` | Messages object with locale keys at top level. |

```js
import { setMessages } from '@soleil-se/i18n';


setMessages({
  en: { hello: 'Hello' },
  sv: { hello: 'Hej'},
});
```

### getMessages()

> **Deprecated**
>
> Use [i18n.getMessages](#i18ngetmessages) instead.

Get all messages for current locale as an object.

```js
import { getMessages } from '@soleil-se/i18n';


console.log(getMessages());
```

### messageExists(path)

> **Deprecated**
>
> Use [i18n.messageExists](#i18nmessageexistspath) instead.

Check if a translation for a message exists or not for the current locale.

**Returns**: `boolean` - If translation of message exists or not.

| Param | Type     | Description          |
| ----- | -------- | -------------------- |
| path  | `string` | Path to message key. |

```js
import { messageExists } from '@soleil-se/i18n';


console.log(messageExists('hello'));
```

### translate(path, \[values]) ⇨ `string`

> **Deprecated**
>
> Use [i18n](#i18npath-values--string) instead.

Translate a message. Also exported as `i18n` and `t`.

**Returns**: `string` - Translated message.

| Param     | Type     | Default | Description                  |
| --------- | -------- | ------- | ---------------------------- |
| path      | `string` |         | Path to message key.         |
| \[values] | `object` | `{}`    | Values to inject in message. |

```js
import { addMessages, translate, i18n, t } from '@soleil-se/i18n';


addMessages('en', { hello: 'Hello'});
addMessages('sv', { hello: 'Hej'});


console.log(translate('hello'));
console.log(i18n('hello'));
console.log(t('hello'));
```

**With values**

```js
import { addMessages, i18n } from '@soleil-se/i18n';


addMessages('en', { hello: 'Hello {name}!'});
addMessages('sv', { hello: 'Hej {name}!'});


console.log(i18n('hello', { name: 'Foo' })); // Hej Foo!
```

## Svelte

If you only need static translations without changing anything on the fly the base API is enough. There is a store wrapper when language needs to be changed dynamically.

### Static

**Demo** <https://svelte.dev/repl/35e4069f38b14b7891fd8fd0ce571dfd?version=4.2.11>

### Dynamic

**Demo** <https://svelte.dev/repl/b17f963e58154b6cb2e211973e561692?version=4.2.11>

**i18n.js**

```js
import { addMessages, i18n, setLocale } from '@soleil-se/i18n/svelte-store';


import en from './en';
import sv from './sv';


addMessages('en', en);
addMessages('sv', sv);


export { i18n, setLocale };
```

**App.svelte**

```svelte
<script>
  import { i18n, setLocale } from './i18n';


  let name = 'Foo';
</script>


<h1>Dynamic</h1>
<button on:click={() => setLocale('en')}>
  English
</button>
<button on:click={() => setLocale('sv')}>
  Svenska
</button>


<label for="name_input">{$i18n('name')}</label>
<input id="name_input" bind:value={name} />


<h2>{$i18n('hello')}</h2>
<p>
  {$i18n('howAreYou', { name })}
</p>
```

## Bundled script module

> **Deprecated**
>
> Bundled script modules should not be used anymore.

Since you can’t call a function in a Velocity template you need to use the `i18n.getMessages` function to export an object with translated messages.\
Injecting values to messages **won’t** work with this method.\
Also prefix the i18n file with underscore, `_i18n.js`.

**i18n.js**

```js
import { createI18n } from '@soleil-se/i18n';


return createI18n({
  en: { hello: 'Hello' },
  sv: { hello: 'Hej' },
}).getMessages();
```

Before 2.4.0**

**\_i18n.js**

```js
import { addMessages, getMessages } from '@soleil-se/i18n';


addMessages('en', { hello: 'Hello'});
addMessages('sv', { hello: 'Hej'});


export default getMessages();
```

**module.js**

```js
import i18n from './_i18n';


export default {
  i18n,
};
```

```html
<p>${i18n.hello}</p>
```