@genrwork/laravel-i18next 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of @genrwork/laravel-i18next might be problematic. Click here for more details.

Files changed (38) hide show
  1. package/README.md +367 -0
  2. package/client.d.ts +12 -0
  3. package/dist/index.cjs +12 -0
  4. package/dist/index.mjs +2 -0
  5. package/dist/react.cjs +40 -0
  6. package/dist/react.mjs +38 -0
  7. package/dist/shared/create-i18n-BSEwKsCX.mjs +641 -0
  8. package/dist/shared/create-i18n-WsDK4Z8L.cjs +647 -0
  9. package/dist/svelte.cjs +77 -0
  10. package/dist/svelte.mjs +74 -0
  11. package/dist/types/backend.d.ts +29 -0
  12. package/dist/types/contrib/get-plural-index.d.ts +15 -0
  13. package/dist/types/format.d.ts +43 -0
  14. package/dist/types/index.d.ts +7 -0
  15. package/dist/types/interfaces/locale-file.d.ts +8 -0
  16. package/dist/types/interfaces/options.d.ts +19 -0
  17. package/dist/types/interfaces/replacements.d.ts +6 -0
  18. package/dist/types/plugin/helper.d.ts +6 -0
  19. package/dist/types/plugin/locale.d.ts +11 -0
  20. package/dist/types/plugin/parser.d.ts +22 -0
  21. package/dist/types/plugin/sources.d.ts +53 -0
  22. package/dist/types/react/i18n-provider-props.d.ts +23 -0
  23. package/dist/types/react/index.d.ts +3 -0
  24. package/dist/types/react/provider.d.ts +10 -0
  25. package/dist/types/shared/create-i18n.d.ts +26 -0
  26. package/dist/types/svelte/index.d.ts +48 -0
  27. package/dist/types/utils/pluralization.d.ts +9 -0
  28. package/dist/types/utils/recognizer.d.ts +29 -0
  29. package/dist/types/utils/replacer.d.ts +9 -0
  30. package/dist/types/utils/resolver.d.ts +23 -0
  31. package/dist/types/utils/sources.d.ts +14 -0
  32. package/dist/types/vite.d.ts +25 -0
  33. package/dist/types/vue/index.d.ts +21 -0
  34. package/dist/vite.cjs +315 -0
  35. package/dist/vite.mjs +310 -0
  36. package/dist/vue.cjs +39 -0
  37. package/dist/vue.mjs +34 -0
  38. package/package.json +155 -0
@@ -0,0 +1,77 @@
1
+ 'use strict';
2
+
3
+ var svelte = require('svelte');
4
+ var store = require('svelte/store');
5
+ var createI18n = require('./shared/create-i18n-WsDK4Z8L.cjs');
6
+ require('i18next');
7
+
8
+ const CONTEXT_KEY = 'laravel-i18next';
9
+ /**
10
+ * Create an i18next instance translating Laravel language files, and make it
11
+ * available to `useTranslation()` in child components.
12
+ *
13
+ * Every call creates its own instance, so concurrent SSR requests do not share
14
+ * a language. Must be called during component initialization (top level of `<script>`).
15
+ *
16
+ * ```svelte
17
+ * <script>
18
+ * import { setLaravelI18nContext } from '@genrwork/laravel-i18next/svelte';
19
+ *
20
+ * setLaravelI18nContext({
21
+ * locale: data.locale,
22
+ * fallbackLocale: 'en',
23
+ * files: import.meta.glob('/lang/**\/*.json'),
24
+ * });
25
+ * </script>
26
+ * ```
27
+ */ function setLaravelI18nContext(options) {
28
+ const i18next = createI18n.createI18n(options);
29
+ const unsubscribe = createI18n.syncDocumentLang(i18next);
30
+ svelte.onDestroy(unsubscribe);
31
+ svelte.setContext(CONTEXT_KEY, i18next);
32
+ return i18next;
33
+ }
34
+ function getI18nextFromContext() {
35
+ if (!svelte.hasContext(CONTEXT_KEY)) {
36
+ throw new Error('No Laravel i18next instance found in context. Call setLaravelI18nContext() in a parent component.');
37
+ }
38
+ return svelte.getContext(CONTEXT_KEY);
39
+ }
40
+ /**
41
+ * A reactive `t()` function and `ready` flag for the given namespace, bound to
42
+ * the i18next instance set with `setLaravelI18nContext()`.
43
+ *
44
+ * ```svelte
45
+ * <script>
46
+ * import { useTranslation } from '@genrwork/laravel-i18next/svelte';
47
+ *
48
+ * const { t } = useTranslation('auth');
49
+ * </script>
50
+ *
51
+ * <p>{$t('failed')}</p>
52
+ * ```
53
+ */ function useTranslation(namespace, i18nextInstance) {
54
+ const instance = i18nextInstance !== null && i18nextInstance !== void 0 ? i18nextInstance : getI18nextFromContext();
55
+ const revision = store.writable(0);
56
+ const bump = ()=>revision.update((n)=>n + 1);
57
+ instance.on('languageChanged', bump);
58
+ instance.on('loaded', bump);
59
+ instance.on('added', bump);
60
+ svelte.onDestroy(()=>{
61
+ instance.off('languageChanged', bump);
62
+ instance.off('loaded', bump);
63
+ instance.off('added', bump);
64
+ });
65
+ const t = store.derived(revision, ()=>instance.getFixedT(null, namespace !== null && namespace !== void 0 ? namespace : null));
66
+ const ready = store.derived(revision, ()=>instance.isInitialized && (!namespace || instance.hasLoadedNamespace(namespace)));
67
+ const language = store.derived(revision, ()=>instance.language);
68
+ return {
69
+ t,
70
+ ready,
71
+ language,
72
+ i18next: instance
73
+ };
74
+ }
75
+
76
+ exports.setLaravelI18nContext = setLaravelI18nContext;
77
+ exports.useTranslation = useTranslation;
@@ -0,0 +1,74 @@
1
+ import { onDestroy, setContext, hasContext, getContext } from 'svelte';
2
+ import { writable, derived } from 'svelte/store';
3
+ import { c as createI18n, s as syncDocumentLang } from './shared/create-i18n-BSEwKsCX.mjs';
4
+ import 'i18next';
5
+
6
+ const CONTEXT_KEY = 'laravel-i18next';
7
+ /**
8
+ * Create an i18next instance translating Laravel language files, and make it
9
+ * available to `useTranslation()` in child components.
10
+ *
11
+ * Every call creates its own instance, so concurrent SSR requests do not share
12
+ * a language. Must be called during component initialization (top level of `<script>`).
13
+ *
14
+ * ```svelte
15
+ * <script>
16
+ * import { setLaravelI18nContext } from '@genrwork/laravel-i18next/svelte';
17
+ *
18
+ * setLaravelI18nContext({
19
+ * locale: data.locale,
20
+ * fallbackLocale: 'en',
21
+ * files: import.meta.glob('/lang/**\/*.json'),
22
+ * });
23
+ * </script>
24
+ * ```
25
+ */ function setLaravelI18nContext(options) {
26
+ const i18next = createI18n(options);
27
+ const unsubscribe = syncDocumentLang(i18next);
28
+ onDestroy(unsubscribe);
29
+ setContext(CONTEXT_KEY, i18next);
30
+ return i18next;
31
+ }
32
+ function getI18nextFromContext() {
33
+ if (!hasContext(CONTEXT_KEY)) {
34
+ throw new Error('No Laravel i18next instance found in context. Call setLaravelI18nContext() in a parent component.');
35
+ }
36
+ return getContext(CONTEXT_KEY);
37
+ }
38
+ /**
39
+ * A reactive `t()` function and `ready` flag for the given namespace, bound to
40
+ * the i18next instance set with `setLaravelI18nContext()`.
41
+ *
42
+ * ```svelte
43
+ * <script>
44
+ * import { useTranslation } from '@genrwork/laravel-i18next/svelte';
45
+ *
46
+ * const { t } = useTranslation('auth');
47
+ * </script>
48
+ *
49
+ * <p>{$t('failed')}</p>
50
+ * ```
51
+ */ function useTranslation(namespace, i18nextInstance) {
52
+ const instance = i18nextInstance !== null && i18nextInstance !== void 0 ? i18nextInstance : getI18nextFromContext();
53
+ const revision = writable(0);
54
+ const bump = ()=>revision.update((n)=>n + 1);
55
+ instance.on('languageChanged', bump);
56
+ instance.on('loaded', bump);
57
+ instance.on('added', bump);
58
+ onDestroy(()=>{
59
+ instance.off('languageChanged', bump);
60
+ instance.off('loaded', bump);
61
+ instance.off('added', bump);
62
+ });
63
+ const t = derived(revision, ()=>instance.getFixedT(null, namespace !== null && namespace !== void 0 ? namespace : null));
64
+ const ready = derived(revision, ()=>instance.isInitialized && (!namespace || instance.hasLoadedNamespace(namespace)));
65
+ const language = derived(revision, ()=>instance.language);
66
+ return {
67
+ t,
68
+ ready,
69
+ language,
70
+ i18next: instance
71
+ };
72
+ }
73
+
74
+ export { setLaravelI18nContext, useTranslation };
@@ -0,0 +1,29 @@
1
+ import type { BackendModule, ReadCallback } from 'i18next';
2
+ import type LaravelBackendOptions from './interfaces/options';
3
+ /**
4
+ * i18next backend loading Laravel language files as separate namespaces from
5
+ * one or more sources, highest priority first: the default namespace from
6
+ * `{source}/{locale}.json`, and one namespace per PHP file from
7
+ * `{source}/{locale}/{namespace}.json` (generated by the Vite plugin from
8
+ * `{namespace}.php`, or hand-written) -- a namespace may also nest to any
9
+ * depth, see `src/utils/recognizer.ts`.
10
+ *
11
+ * When several sources have a file for the same `(locale, namespace)`, they
12
+ * are merged per key: a higher-priority source's key overrides a
13
+ * lower-priority one, but a key present only in a lower-priority source still
14
+ * resolves. This is what lets a namespace migrate from PHP to hand-written
15
+ * JSON one string at a time.
16
+ *
17
+ * Eager files are read synchronously, lazy files asynchronously -- and the
18
+ * whole read stays synchronous as long as every candidate for the pair is
19
+ * eager, even when several sources contribute, which SSR depends on
20
+ * (`initAsync: false` + `preload`). A (locale, namespace) pair without a
21
+ * matching file in any source gets no resources.
22
+ */
23
+ export default class LaravelBackend implements BackendModule<LaravelBackendOptions> {
24
+ static type: "backend";
25
+ type: "backend";
26
+ private files;
27
+ init(_services: unknown, backendOptions?: Partial<LaravelBackendOptions>): void;
28
+ read(language: string, namespace: string, callback: ReadCallback): void;
29
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Get the index to use for pluralization.
3
+ * The plural rules are derived from code of the Zend Framework.
4
+ *
5
+ * @category Zend
6
+ * @package Zend_Locale
7
+ * @public https://github.com/zendframework/zf1/blob/master/library/Zend/Translate/Plural.php
8
+ * @copyright 2005-2015 Zend Technologies USA Inc. http://www.zend.com
9
+ * @license http://framework.zend.com/license New BSD License
10
+ *
11
+ * @param {String} locale
12
+ * @param {Number} number
13
+ * @return {Number}
14
+ */
15
+ export declare function getPluralIndex(locale: string, number: number): 1 | 0 | 3 | 2 | 4 | 5;
@@ -0,0 +1,43 @@
1
+ import type { i18n, TOptions } from 'i18next';
2
+ /**
3
+ * i18next format plugin translating the way Laravel does:
4
+ *
5
+ * - flat keys (`auth.failed`, `Welcome, :name!`), no key or namespace separators;
6
+ * - `:name`, `:NAME` and `:Name` replacements instead of `{{name}}` interpolation and `$t()` nesting;
7
+ * - a numeric `count` selects the message with Laravel's `trans_choice()` rules
8
+ * (`one|many`, `{0} none|[1,19] some|[20,*] many`) instead of `_one`/`_other` suffixed keys;
9
+ * - empty messages fall back to the next language.
10
+ */
11
+ export default class LaravelFormat {
12
+ static type: "i18nFormat";
13
+ type: "i18nFormat";
14
+ /**
15
+ * Non-string translations (e.g. an empty PHP array) are returned as is.
16
+ */
17
+ handleAsObject: boolean;
18
+ private i18next?;
19
+ init(i18next: i18n): void;
20
+ getResource(language: string, namespace: string, key: string): any;
21
+ addLookupKeys(finalKeys: string[]): string[];
22
+ parse(message: unknown, options: TOptions, language: string, namespace: string, _key?: string, info?: {
23
+ resolved?: {
24
+ usedLng?: string;
25
+ };
26
+ }): unknown;
27
+ /**
28
+ * The language the message actually resolved in, so pluralization always
29
+ * matches the text being pluralized -- never merely a language that has
30
+ * translations for the namespace, which is not the same thing once several
31
+ * sources can contribute to one namespace (see LaravelBackend): a single
32
+ * unrelated key from a higher-priority source is enough to make
33
+ * `hasResourceBundle(language, namespace)` true for a namespace whose
34
+ * actual message still came from the fallback language.
35
+ *
36
+ * i18next passes the language the lookup succeeded at as `resolved.usedLng`
37
+ * in `parse()`'s 6th argument (`extendTranslation()` in i18next's own
38
+ * `translator.js`); prefer it. Older i18next in the `>=24` peer range that
39
+ * does not pass it falls back to a heuristic: the current language when it
40
+ * has translations for the namespace, else the fallback language.
41
+ */
42
+ private getPluralLocale;
43
+ }
@@ -0,0 +1,7 @@
1
+ import LaravelBackend from './backend';
2
+ import LaravelFormat from './format';
3
+ export { LaravelBackend, LaravelFormat };
4
+ export { createI18n, documentLocale, syncDocumentLang } from './shared/create-i18n';
5
+ export type { LaravelI18nOptions } from './shared/create-i18n';
6
+ export type { default as LaravelBackendOptions, LocaleFiles, LocaleFileSources } from './interfaces/options';
7
+ export type { default as ReplacementsInterface } from './interfaces/replacements';
@@ -0,0 +1,8 @@
1
+ /**
2
+ * A resolved language file module.
3
+ */
4
+ export default interface LocaleFileInterface {
5
+ default: {
6
+ [key: string]: string;
7
+ };
8
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Language files as returned by `import.meta.glob('/lang/*.json')`,
3
+ * either lazy (loader functions) or eager (modules).
4
+ */
5
+ export type LocaleFiles = Record<string, unknown> | Record<string, () => Promise<unknown>>;
6
+ /**
7
+ * One or more `LocaleFiles` maps, highest priority first. A single map is a
8
+ * one-source project; an array layers several sources, resolving each key from
9
+ * the highest-priority source that has it (see `toSources()` in
10
+ * `src/utils/sources.ts`). The Vite plugin's `sources` option always produces
11
+ * an array, one entry per configured source, in the same order.
12
+ */
13
+ export type LocaleFileSources = LocaleFiles | LocaleFiles[];
14
+ /**
15
+ * Options of `LaravelBackend`, given as the `backend` option of i18next.
16
+ */
17
+ export default interface LaravelBackendOptions {
18
+ files: LocaleFileSources;
19
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Placeholder replacements, e.g. `{ name: 'Francisco' }` for `:name`.
3
+ */
4
+ export default interface ReplacementsInterface {
5
+ [key: string]: string | number;
6
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Normalize the separators of a directory name and ensure a trailing separator.
3
+ *
4
+ * @param rawDirname
5
+ */
6
+ export declare function dirnameSanitize(rawDirname: string): string;
@@ -0,0 +1,11 @@
1
+ declare const _default: {
2
+ /**
3
+ * Locales having a `lang/{locale}/` directory containing PHP files,
4
+ * however deep -- a locale whose PHP all lives in a nested namespace
5
+ * subdirectory still counts.
6
+ *
7
+ * @param dirname
8
+ */
9
+ getPhpLocale: (dirname: string) => string[];
10
+ };
11
+ export default _default;
@@ -0,0 +1,22 @@
1
+ export interface GeneratedFile {
2
+ path: string;
3
+ basename: string;
4
+ }
5
+ /**
6
+ * Convert every `lang/{locale}/{namespace}.php` file into a sibling
7
+ * `lang/{locale}/{namespace}.json` file, one per PHP file, so each PHP file
8
+ * becomes its own i18next namespace instead of being merged with the others.
9
+ * A PHP file may sit at any depth under the locale directory --
10
+ * `lang/{locale}/{ns1}/{ns2}.php` and deeper -- and gets its sibling `.json`
11
+ * written at that same nested path; the resulting namespace name itself is
12
+ * inferred later, from the generated file's path, by `src/utils/recognizer.ts`.
13
+ *
14
+ * A source meant to hold hand-written JSON (e.g. a frontend-only catalog)
15
+ * should never also hold PHP files of the same name -- this directory is a
16
+ * PHP source, so its sibling `.json` is always regenerated, overwriting
17
+ * whatever was there before (including a leftover from a previous, uncleaned
18
+ * run). Keep hand-written translations in their own source directory.
19
+ *
20
+ * @param dirname
21
+ */
22
+ export default function parser(dirname: string): GeneratedFile[];
@@ -0,0 +1,53 @@
1
+ /**
2
+ * One configured source, resolved against the project root.
3
+ */
4
+ export interface ResolvedSource {
5
+ /** As configured, e.g. `'Modules/*\/lang'`. */
6
+ pattern: string;
7
+ /** Root-relative glob for `import.meta.glob()`, e.g. `'/Modules/*\/lang/**\/*.json'`. */
8
+ glob: string;
9
+ /** Every directory the pattern currently expands to, existing ones only, sorted. */
10
+ dirnames: string[];
11
+ }
12
+ /**
13
+ * Every directory an ordered source `pattern` currently expands to, relative
14
+ * to `root`. A pattern with no `*` is a single literal directory (existing or
15
+ * not -- callers decide what an absent literal directory means). A pattern
16
+ * with exactly one `*` segment (e.g. `Modules/*\/lang`) is expanded against
17
+ * the filesystem: every existing subdirectory of the prefix before the `*`,
18
+ * with the suffix after it appended, kept only when the full path also
19
+ * exists, sorted. Two or more `*` segments throw -- unsupported.
20
+ *
21
+ * @param pattern
22
+ * @param root
23
+ */
24
+ export declare function expandDirs(pattern: string, root: string): string[];
25
+ /**
26
+ * The root-relative glob `import.meta.glob()` needs for a source pattern.
27
+ * Globs inside a virtual module have no containing file to be relative to,
28
+ * so this is always root-relative (a leading `/`). A `*` segment in the
29
+ * pattern passes through `path.resolve`/`path.relative`/`normalizePath`
30
+ * completely untouched -- none of them treat it specially -- which is why
31
+ * the emitted glob needs no separate wildcard handling: `Modules/*\/lang`
32
+ * becomes `/Modules/*\/lang/**\/*.json` and `import.meta.glob()` expands the
33
+ * `*` itself, natively, at both dev and build time.
34
+ *
35
+ * @param pattern
36
+ * @param root
37
+ */
38
+ export declare function toGlob(pattern: string, root: string): string;
39
+ /**
40
+ * Resolve every configured source pattern, in the given order.
41
+ *
42
+ * @param patterns
43
+ * @param root
44
+ */
45
+ export declare function resolveSources(patterns: string[], root: string): ResolvedSource[];
46
+ /**
47
+ * Whether `file` sits under one of `dirnames` (any depth) -- used to decide
48
+ * whether a changed file belongs to any configured source at all.
49
+ *
50
+ * @param file
51
+ * @param dirnames
52
+ */
53
+ export declare function isUnderAnySource(file: string, dirnames: string[]): boolean;
@@ -0,0 +1,23 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { LocaleFileSources } from '../interfaces/options';
3
+ /**
4
+ * Props of `<LaravelReactI18nProvider>`.
5
+ */
6
+ export default interface I18nProviderProps {
7
+ children: ReactNode;
8
+ /**
9
+ * Language files: `virtual:laravel-i18next/files` (an ordered array, one
10
+ * entry per configured `sources`, highest priority first), or a single
11
+ * `import.meta.glob('/lang/**\/*.json')` (lazy) /
12
+ * `import.meta.glob('/lang/**\/*.json', { eager: true })` (eager).
13
+ */
14
+ files: LocaleFileSources;
15
+ /**
16
+ * Defaults to the `<html lang="">` attribute, or `en`.
17
+ */
18
+ locale?: string;
19
+ /**
20
+ * Defaults to the `<html lang="">` attribute, or `en`.
21
+ */
22
+ fallbackLocale?: string;
23
+ }
@@ -0,0 +1,3 @@
1
+ import LaravelReactI18nProvider from './provider';
2
+ export { LaravelReactI18nProvider };
3
+ export type { default as I18nProviderProps } from './i18n-provider-props';
@@ -0,0 +1,10 @@
1
+ import type I18nProviderProps from './i18n-provider-props';
2
+ /**
3
+ * Provides an i18next instance translating Laravel language files to react-i18next.
4
+ *
5
+ * Every provider owns its instance, so concurrent SSR requests do not share a language.
6
+ * With eager files, every namespace is preloaded and translated on the first render.
7
+ * While a lazy namespace loads, the children suspend, which keeps server-rendered
8
+ * HTML in place until it can be hydrated.
9
+ */
10
+ export default function LaravelReactI18nProvider({ children, files, locale, fallbackLocale }: I18nProviderProps): import("react").JSX.Element;
@@ -0,0 +1,26 @@
1
+ import type { i18n } from 'i18next';
2
+ import type { LocaleFileSources } from '../interfaces/options';
3
+ export interface LaravelI18nOptions {
4
+ files: LocaleFileSources;
5
+ locale?: string;
6
+ fallbackLocale?: string;
7
+ }
8
+ /**
9
+ * Locale of the `<html lang="">` attribute (set by Laravel's `app.blade.php`), or `en`.
10
+ */
11
+ export declare function documentLocale(): string;
12
+ /**
13
+ * Set the `<html lang="">` attribute to the instance's current language, and keep it
14
+ * in sync whenever the language changes afterwards.
15
+ */
16
+ export declare function syncDocumentLang(instance: i18n): () => void;
17
+ /**
18
+ * Create an i18next instance translating Laravel language files: the default
19
+ * namespace from `lang/{locale}.json`, and one namespace per `lang/{locale}/{namespace}.json`
20
+ * file (generated by the Vite plugin, or hand-written).
21
+ *
22
+ * With eager files, every known namespace of the locale and fallback locale is
23
+ * preloaded synchronously, so a first render never has to wait for translations.
24
+ * With lazy files, namespaces are loaded on demand as components request them.
25
+ */
26
+ export declare function createI18n({ files, locale, fallbackLocale }: LaravelI18nOptions): i18n;
@@ -0,0 +1,48 @@
1
+ import { type Readable } from 'svelte/store';
2
+ import type { i18n, TFunction } from 'i18next';
3
+ import type { LaravelI18nOptions } from '../shared/create-i18n';
4
+ export interface Translation<N extends string = string> {
5
+ /** The current translation function, reactive to language and namespace loading. */
6
+ t: Readable<TFunction<N>>;
7
+ /** Whether the namespace is loaded (always `true` with eager files). */
8
+ ready: Readable<boolean>;
9
+ /** The current language, reactive to `changeLanguage()`. */
10
+ language: Readable<string>;
11
+ /** The underlying i18next instance. Not itself reactive; prefer `t`, `ready` and `language`. */
12
+ i18next: i18n;
13
+ }
14
+ /**
15
+ * Create an i18next instance translating Laravel language files, and make it
16
+ * available to `useTranslation()` in child components.
17
+ *
18
+ * Every call creates its own instance, so concurrent SSR requests do not share
19
+ * a language. Must be called during component initialization (top level of `<script>`).
20
+ *
21
+ * ```svelte
22
+ * <script>
23
+ * import { setLaravelI18nContext } from '@genrwork/laravel-i18next/svelte';
24
+ *
25
+ * setLaravelI18nContext({
26
+ * locale: data.locale,
27
+ * fallbackLocale: 'en',
28
+ * files: import.meta.glob('/lang/**\/*.json'),
29
+ * });
30
+ * </script>
31
+ * ```
32
+ */
33
+ export declare function setLaravelI18nContext(options: LaravelI18nOptions): i18n;
34
+ /**
35
+ * A reactive `t()` function and `ready` flag for the given namespace, bound to
36
+ * the i18next instance set with `setLaravelI18nContext()`.
37
+ *
38
+ * ```svelte
39
+ * <script>
40
+ * import { useTranslation } from '@genrwork/laravel-i18next/svelte';
41
+ *
42
+ * const { t } = useTranslation('auth');
43
+ * </script>
44
+ *
45
+ * <p>{$t('failed')}</p>
46
+ * ```
47
+ */
48
+ export declare function useTranslation<N extends string = string>(namespace?: N, i18nextInstance?: i18n): Translation<N>;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Select a proper translation string based on the given number,
3
+ * using the same rules as Laravel's `trans_choice()`.
4
+ *
5
+ * @param message
6
+ * @param number
7
+ * @param locale
8
+ */
9
+ export default function pluralization(message: string, number: number, locale: string): string;
@@ -0,0 +1,29 @@
1
+ import type { LocaleFileSources } from '../interfaces/options';
2
+ /**
3
+ * The i18next namespace of a flat `lang/{locale}.json` file (i18next's own default).
4
+ */
5
+ export declare const DEFAULT_NAMESPACE = "translation";
6
+ /**
7
+ * A candidate file for a `(locale, namespace)` pair: `source` is the index of
8
+ * the `LocaleFileSources` entry it came from (lower = higher priority).
9
+ */
10
+ export interface Candidate {
11
+ source: number;
12
+ file: string;
13
+ }
14
+ /**
15
+ * Recognize the locales and namespaces available from one or more
16
+ * `LocaleFileSources`, highest priority first.
17
+ *
18
+ * @param files
19
+ */
20
+ export default function recognizer(files: LocaleFileSources): {
21
+ isLocale: (locale: string) => boolean;
22
+ getLocales: () => string[];
23
+ getNamespaces: (locale: string) => string[];
24
+ getAllNamespaces: () => string[];
25
+ /** The single highest-priority file, or `undefined` when none exists. */
26
+ getFile: (locale: string, namespace: string) => string | undefined;
27
+ /** Every candidate file for the pair, highest priority first. */
28
+ getCandidates: (locale: string, namespace: string) => Candidate[];
29
+ };
@@ -0,0 +1,9 @@
1
+ import type ReplacementsInterface from '../interfaces/replacements';
2
+ /**
3
+ * Make the place-holder replacements on a line, the Laravel way:
4
+ * `:name` as is, `:NAME` upper-cased and `:Name` capitalized.
5
+ *
6
+ * @param message
7
+ * @param replacements
8
+ */
9
+ export default function replacer(message: string, replacements?: ReplacementsInterface): string;
@@ -0,0 +1,23 @@
1
+ import type LocaleFileInterface from '../interfaces/locale-file';
2
+ import type { LocaleFileSources } from '../interfaces/options';
3
+ /**
4
+ * One resolved candidate: a module directly (eager `import.meta.glob`, or a
5
+ * plain object) or a promise of one (lazy `import.meta.glob`, or a loader
6
+ * function already called).
7
+ */
8
+ export type ResolvedFile = LocaleFileInterface | Promise<LocaleFileInterface>;
9
+ /**
10
+ * Resolve every candidate language file of a locale's namespace, highest
11
+ * priority first (see `recognizer().getCandidates()`). Each candidate keeps
12
+ * its own shape -- eager candidates stay synchronous, lazy ones stay a
13
+ * promise -- so a caller merging them can still take an all-synchronous path
14
+ * when every candidate happens to be eager.
15
+ *
16
+ * An empty array means the locale has no file at all for that namespace, in
17
+ * any source.
18
+ *
19
+ * @param files
20
+ * @param locale
21
+ * @param namespace
22
+ */
23
+ export default function resolver(files: LocaleFileSources, locale: string, namespace: string): ResolvedFile[];
@@ -0,0 +1,14 @@
1
+ import type { LocaleFiles, LocaleFileSources } from '../interfaces/options';
2
+ /**
3
+ * Normalize a `LocaleFileSources` (a single `LocaleFiles` map, or an ordered
4
+ * array of them, highest priority first) into an array, always -- a bare
5
+ * map behaves like a single-entry array. Non-object entries (e.g. `null`,
6
+ * defensively) are dropped rather than throwing, so a hand-built array with a
7
+ * gap does not crash the whole app.
8
+ *
9
+ * `Array.isArray` is the discriminator: `LocaleFiles` is itself a plain
10
+ * `Record<string, unknown>`, which is why every consumer of `files` must call
11
+ * this before treating it as a map of maps -- `Object.keys()` on a raw array
12
+ * would otherwise yield `'0'`, `'1'`, ... instead of file paths.
13
+ */
14
+ export declare function toSources(files: LocaleFileSources): LocaleFiles[];
@@ -0,0 +1,25 @@
1
+ import type { PluginOption } from 'vite';
2
+ export interface ConfigInterface {
3
+ /**
4
+ * Ordered, highest priority first. Each entry directory may contain
5
+ * hand-written `.json` files, `.php` files (each converted to a sibling
6
+ * `.json`), or both -- but not both for the same namespace, since a
7
+ * hand-written file is never overwritten (see `src/plugin/parser.ts`).
8
+ * One `*` segment is allowed per entry, e.g. `'Modules/*\/lang'`, expanded
9
+ * against every matching directory that exists when the dev server starts
10
+ * or a build runs. Defaults to `['lang']`.
11
+ */
12
+ sources?: string[];
13
+ }
14
+ /**
15
+ * Language files, one namespace per language file: loaded eagerly by server
16
+ * code (SSR), so it renders translated, and lazily by client code. The
17
+ * default export is an ARRAY, one entry per configured source in `sources`,
18
+ * highest priority first (see `LocaleFileSources` in `src/interfaces/options.ts`).
19
+ */
20
+ export declare const FILES_MODULE_ID = "virtual:laravel-i18next/files";
21
+ /**
22
+ * Makes Laravel PHP translations available to i18next by generating a sibling
23
+ * `.json` file next to each `.php` file, across one or more ordered sources.
24
+ */
25
+ export default function i18n(config?: ConfigInterface): PluginOption;
@@ -0,0 +1,21 @@
1
+ import type { Plugin } from 'vue';
2
+ import { useTranslation } from 'i18next-vue';
3
+ import type { LaravelI18nOptions } from '../shared/create-i18n';
4
+ export { useTranslation };
5
+ /**
6
+ * Vue plugin providing an i18next instance translating Laravel language files
7
+ * to `i18next-vue`'s `useTranslation()` composable and `$t`/`$i18next`.
8
+ *
9
+ * Every app instance owns its own i18next instance, so concurrent SSR requests
10
+ * do not share a language.
11
+ *
12
+ * ```ts
13
+ * import { createApp } from 'vue';
14
+ * import { laravelVueI18n } from '@genrwork/laravel-i18next/vue';
15
+ *
16
+ * createApp(App)
17
+ * .use(laravelVueI18n({ locale: 'uk', fallbackLocale: 'en', files: import.meta.glob('/lang/**\/*.json') }))
18
+ * .mount('#app');
19
+ * ```
20
+ */
21
+ export declare function laravelVueI18n(options: LaravelI18nOptions): Plugin;