Skip to content

Configuration file

ember-intl strives to be "zero config." That is, its defaults should already cover 80% of the use cases. It supports the remaining ones with the help of a configuration file.

For v1 apps, create config/ember-intl.js (CJS). The file is to default-export a function, which returns the build options as an object. Only @ember-intl/v1-compat uses this file.

js
module.exports = function (/* environment */) {
  return {
    fallbackLocale: 'en-us',
  };
};

For v2 apps, create ember-intl.config.{js,mjs,mts,ts} (ESM). The file must default-export an object, which may include addonPaths, buildOptions, and lintOptions. Only @ember-intl/lint and @ember-intl/vite make use of this file.

js
export default {
  buildOptions: {
    fallbackLocale: 'en-us',
  },
};
ts
import type { UserConfig } from 'ember-intl/config';

export default {
  buildOptions: {
    fallbackLocale: 'en-us',
  },
} satisfies UserConfig;
ts
import { defineConfig } from 'ember-intl/config';

export default defineConfig({
  buildOptions: {
    fallbackLocale: 'en-us',
  },
});

TIP

Only specify the key(s) whose default value you want to override. That is, your configuration file should easily show what's different about your app or addon.

TIP

UserConfig uses Partial's, which can unintentionally allow undefined. In tsconfig.json, set compilerOptions.exactOptionalPropertyTypes to true for strict type checks.

NOTE

Any app or addon that uses @ember-intl/lint can have ember-intl.config.{js,mjs,mts,ts}.

As a result, v1 apps and v1 addons can have two configuration files with some duplicate code. Once you migrate a v1 app to v2, you can delete config/ember-intl.js. For v1 addons, delete tests/dummy/config/ember-intl.js.

addonPaths ​

To include an addon's translations, specify the relative path to the addon's root.

ts
import type { UserConfig } from 'ember-intl/config';

export default {
  addonPaths: ['node_modules/my-v1-addon', 'node_modules/my-v2-addon'],
} satisfies UserConfig;

TIP

If multiple addons define the same key, the last appearing addon's translation wins. (This isn't possible with @ember-intl/v1-compat.)

You can override an addon's translation in the consuming app. If the app uses the same key in its own translation file, the app's translation always wins.

buildOptions ​

The buildOptions object assumes the following shape and default values.

ts
type BuildOptions = {
  bundleSeparately: boolean;  // Only for `@ember-intl/v1-compat`
  fallbackLocale: string | undefined;
  namespaceKeysByDir: boolean;
  translationsDir: string;
};
ts
const defaultBuildOptions = {
  bundleSeparately: false,  // Only for `@ember-intl/v1-compat`
  fallbackLocale: undefined,
  namespaceKeysByDir: false,
  translationsDir: 'translations',
};

bundleSeparately Only for v1 apps ​

Prevents the translations from being bundled with the application code. This enables lazily loading the translations.

js
module.exports = function (/* environment */) {
  return {
    bundleSeparately: true,
  };
};

For more information, see Advanced - Lazy-loading translations.

fallbackLocale ​

Copies the fallback locale's translation to all other locales' that are missing a key.

ts
import type { UserConfig } from 'ember-intl/config';

export default {
  buildOptions: {
    fallbackLocale: 'en-us',
  },
} satisfies UserConfig;

namespaceKeysByDir ​

Derives the key's namespace from the folder path. Can be used to separate translations by where they are used in the source directory.

ts
import type { UserConfig } from 'ember-intl/config';

export default {
  buildOptions: {
    namespaceKeysByDir: true,
  },
} satisfies UserConfig;

For more information, see Advanced - Organizing translations.

translationsDir ​

Specifies where translations live relative to the project root.

For example, if an app has stored them in public/assets/translations:

ts
import type { UserConfig } from 'ember-intl/config';

export default {
  buildOptions: {
    translationsDir: 'public/assets/translations',
  },
} satisfies UserConfig;

If a v1 addon's dummy app provides its own translations (these aren't published):

js
module.exports = function (/* environment */) {
  return {
    translationsDir: 'tests/dummy/translations',
  };
};

lintOptions Only for @ember-intl/lint ​

The lintOptions object assumes the following shape and default values.

ts
type LintOptions = {
  rules: Record<LintRule, boolean | LintRuleOptions>;
};

rules ​

To disable a rule, pass false.

ts
import type { UserConfig } from 'ember-intl/config';

export default {
  lintOptions: {
    rules: {
      'no-inconsistent-messages': false,
    },
  },
} satisfies UserConfig;

Lint rules may provide options (always configured as an object). For example, a rule may allow the ignores option so that you can ignore translation keys that fail.

ts
import type { UserConfig } from 'ember-intl/config';

export default {
  lintOptions: {
    rules: {
      'no-unused-keys': {
        ignores: ['hello.message', /^backend\.error\./],
      },
    },
  },
} satisfies UserConfig;

Visit @ember-intl/lint's README to learn more about the available rules.