Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,35 @@ export default defineConfig({
});
```

#### Vite plugin options

In addition to that, you can use this `Vite` plugin with additional paths to load from, this is usefull when you are using a package that let's you override your translations, or in case you are getting your application's lang files from different paths.

Note that if one key found in two paths, priority will be given to the last given path between these two (In this example translation key will be loaded from `public/locales`)

```js
// vite.config.js
import i18n from 'laravel-vue-i18n/vite';

export default defineConfig({
plugins: [
laravel([
'resources/css/app.css'
'resources/js/app.js',
]),
vue(),

i18n({
// you can also change your langPath here
// langPath: 'locales'
additionalLangPaths: [
'public/locales' // Load translations from this path too!
]
}),
],
});
```

> During the `npm run dev` execution time, the plugin will create some files like this `php_{lang}.json` on your lang folder.
> And to avoid that to be commited to your code base, I suggest to your `.gitignore` this like:

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/interfaces/plugin-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@ import { OptionsInterface } from './options'
export interface PluginOptionsInterface extends OptionsInterface {
shared?: boolean
}

export interface VitePluginOptionsInterface {
langPath?: string
additionalLangPaths?: string[]
}
3 changes: 3 additions & 0 deletions src/loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,9 @@ export const readThroughDir = (dir) => {
return data
}

export const prepareExtendedParsedLangFiles = (langPaths: string[]) =>
langPaths.reduce((acc, langPath) => [...acc, ...parseAll(langPath)], new Array<ParsedLangFileInterface>())

export const generateFiles = (langPath: string, data: ParsedLangFileInterface[]): ParsedLangFileInterface[] => {
data = mergeData(data)

Expand Down
18 changes: 13 additions & 5 deletions src/vite.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import path from 'path'
import { existsSync, writeFileSync, unlinkSync, readdirSync, rmdirSync } from 'fs'
import { parseAll, hasPhpTranslations, generateFiles } from './loader'
import { existsSync, unlinkSync, readdirSync, rmdirSync } from 'fs'
import { hasPhpTranslations, generateFiles, prepareExtendedParsedLangFiles } from './loader'
import { ParsedLangFileInterface } from './interfaces/parsed-lang-file'
import { VitePluginOptionsInterface } from './interfaces/plugin-options'
import { Plugin } from 'vite'

export default function i18n(langPath: string = 'lang'): Plugin {
export default function i18n(options: string | VitePluginOptionsInterface = 'lang'): Plugin {
let langPath = typeof options === 'string' ? options : options.langPath ?? 'lang'
langPath = langPath.replace(/[\\/]$/, '') + path.sep

const additionalLangPaths = typeof options === 'string' ? [] : options.additionalLangPaths ?? []

const frameworkLangPath = 'vendor/laravel/framework/src/Illuminate/Translation/lang/'.replace('/', path.sep)
let files: ParsedLangFileInterface[] = []
let exitHandlersBound: boolean = false
Expand Down Expand Up @@ -40,11 +44,15 @@ export default function i18n(langPath: string = 'lang'): Plugin {
return
}

files = generateFiles(langPath, [...parseAll(frameworkLangPath), ...parseAll(langPath)])
const langPaths = prepareExtendedParsedLangFiles([frameworkLangPath, langPath, ...additionalLangPaths])

files = generateFiles(langPath, langPaths)
},
handleHotUpdate(ctx) {
if (/lang\/.*\.php$/.test(ctx.file)) {
files = generateFiles(langPath, [...parseAll(frameworkLangPath), ...parseAll(langPath)])
const langPaths = prepareExtendedParsedLangFiles([frameworkLangPath, langPath, ...additionalLangPaths])

files = generateFiles(langPath, langPaths)
}
},
configureServer(server) {
Expand Down
6 changes: 6 additions & 0 deletions test/fixtures/locales/en/auth.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php

return [
'failed' => 'These credentials are incorrect.',
'throttle' => 'Too many login attempts. Please try again in :seconds seconds.'
];
5 changes: 5 additions & 0 deletions test/fixtures/locales/en/domain/user.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

return [
'sub_dir_support_is_amazing' => 'Subdirectory override is amazing',
];
39 changes: 38 additions & 1 deletion test/loader.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import fs from 'fs';
import { generateFiles, parseAll, parse, hasPhpTranslations, reset } from '../src/loader';
import { generateFiles, parseAll, parse, hasPhpTranslations, reset, prepareExtendedParsedLangFiles } from '../src/loader';

beforeEach(() => reset(__dirname + '/fixtures/lang/'));

Expand Down Expand Up @@ -41,6 +41,43 @@ it('includes .php lang file in nested subdirectory in .json', () => {
expect(langEn['nested.cars.car.foo.level1.level2']).toBe('barpt');
})

it('inclues additional lang paths to load from', () => {
const langPath = __dirname + '/fixtures/lang/';
const additionalLangPaths = [
__dirname + '/fixtures/locales/'
];

const langPaths = prepareExtendedParsedLangFiles([
langPath,
...additionalLangPaths,
]);

const files = generateFiles(langPath, langPaths);

const langEn = JSON.parse(fs.readFileSync(langPath + files[0].name).toString());

expect(langEn['auth.throttle']).toBe('Too many login attempts. Please try again in :seconds seconds.');
});

it('overwrites translations from additional lang paths', () => {
const langPath = __dirname + '/fixtures/lang/';
const additionalLangPaths = [
__dirname + '/fixtures/locales/'
];

const langPaths = prepareExtendedParsedLangFiles([
langPath,
...additionalLangPaths,
]);

const files = generateFiles(langPath, langPaths);

const langEn = JSON.parse(fs.readFileSync(langPath + files[0].name).toString());

expect(langEn['auth.failed']).toBe('These credentials are incorrect.');
expect(langEn['domain.user.sub_dir_support_is_amazing']).toBe('Subdirectory override is amazing');
});

it('transforms .php lang to .json', () => {
const lang = parse(fs.readFileSync(__dirname + '/fixtures/lang/en/auth.php').toString());

Expand Down