Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
0c8dd0f
feat: add react-core external store context
ErnestM1234 May 14, 2026
41da9ff
fix: lint
ErnestM1234 May 15, 2026
0a35a3d
merge
ErnestM1234 May 15, 2026
6b7df80
fix lint
ErnestM1234 May 15, 2026
da5f32e
fix: update react-core external store tests
ErnestM1234 May 15, 2026
2aa828d
fix: add getLocale
ErnestM1234 May 15, 2026
5c17a32
fix: prepare context external store for review
ErnestM1234 May 15, 2026
2ff0221
fix: align dictionary update flow
ErnestM1234 May 15, 2026
de89dbf
refactor name
ErnestM1234 May 15, 2026
ca766d9
refactor to new getters
ErnestM1234 May 15, 2026
1ed896f
move condition store to gt-i18n
ErnestM1234 May 15, 2026
8f3b80f
remove fallback condition store
ErnestM1234 May 15, 2026
daa07d1
clean up condition stores
ErnestM1234 May 15, 2026
36382cf
update ssr
ErnestM1234 May 15, 2026
38d6ad3
wip
ErnestM1234 May 15, 2026
cd117ea
refactor: move tings
ErnestM1234 May 15, 2026
09a4e78
cleanup ts start
ErnestM1234 May 15, 2026
48a8204
wip
ErnestM1234 May 15, 2026
dfbbef5
tanstack
ErnestM1234 May 16, 2026
0d567c5
move over helper functions
ErnestM1234 May 16, 2026
8fdcbd9
refactor: move old code
ErnestM1234 May 16, 2026
de70364
move all files into deprecated
ErnestM1234 May 16, 2026
7c77bd4
move files
ErnestM1234 May 16, 2026
679d842
fix: build
ErnestM1234 May 16, 2026
f283b03
refactor new files
ErnestM1234 May 16, 2026
719ac0f
refactor
ErnestM1234 May 16, 2026
6b59470
fix: build issue
ErnestM1234 May 16, 2026
f3df15e
refactor
ErnestM1234 May 16, 2026
d9cb9bd
fix: build issue
ErnestM1234 May 16, 2026
e1e1d3f
yay
ErnestM1234 May 16, 2026
b2dae4b
testing tanstack
ErnestM1234 May 16, 2026
d285fd9
fix: tanstack
ErnestM1234 May 16, 2026
4fd895a
wip
ErnestM1234 May 18, 2026
4eed8db
add more exports
ErnestM1234 May 18, 2026
fb48ecf
changeset
ErnestM1234 May 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/separate-external-store-conditions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@generaltranslation/react-core": major
"gt-react": major
"gt-i18n": major
"gt-tanstack-start": major
"gt-next": major
---

useSyncExternalStore refactor
47 changes: 47 additions & 0 deletions packages/i18n/src/condition-store/ReadonlyConditionStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import type {
LocaleResolverConfig,
ReadonlyConditionStoreInterface as ReadonlyConditionStoreContract,
} from "../i18n-manager/types";
import { createLocaleResolver, type LocaleCandidates } from "./localeResolver";

export type ReadonlyConditionStoreParams = LocaleResolverConfig & {
locale: LocaleCandidates;
enableI18n?: boolean;
};

export class ReadonlyConditionStore implements ReadonlyConditionStoreContract {
/**
* @deprecated use getI18nManager().determineLocale() instead
*/
protected readonly resolveLocale: (candidates?: LocaleCandidates) => string;
protected locale: string;
protected enableI18n: boolean;

constructor({
locale,
enableI18n = true,
...localeConfig
}: ReadonlyConditionStoreParams) {
/**
* TODO: change this to getI18nManager().determineLocale() but this
* currently creates a circular dependency
*/
this.resolveLocale = createLocaleResolver(localeConfig);
this.locale = this.resolveLocale(locale);
this.enableI18n = enableI18n;
}

getLocale = (): string => {
return this.locale;
};

getEnableI18n = (): boolean => {
return this.enableI18n;
};

// --- no-op methods --- //

setLocale = (locale: LocaleCandidates): void => {};

Check warning on line 44 in packages/i18n/src/condition-store/ReadonlyConditionStore.ts

View workflow job for this annotation

GitHub Actions / lint

eslint(no-unused-vars)

Parameter 'locale' is declared but never used. Unused parameters should start with a '_'.

setEnableI18n = (enableI18n: boolean): void => {};

Check warning on line 46 in packages/i18n/src/condition-store/ReadonlyConditionStore.ts

View workflow job for this annotation

GitHub Actions / lint

eslint(no-unused-vars)

Parameter 'enableI18n' is declared but never used. Unused parameters should start with a '_'.
}
22 changes: 22 additions & 0 deletions packages/i18n/src/condition-store/WritableConditionStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { LocaleCandidates } from "../i18n-manager";
import type { WritableConditionStoreInterface as WritableConditionStoreContract } from "../i18n-manager/types";
import {
ReadonlyConditionStore,
type ReadonlyConditionStoreParams,
} from "./ReadonlyConditionStore";

export type WritableConditionStoreParams = ReadonlyConditionStoreParams;

export class WritableConditionStore
extends ReadonlyConditionStore
implements WritableConditionStoreContract
{
setLocale = (locale: LocaleCandidates): void => {
console.log("WritableConditionStore.setLocale", locale);
this.locale = this.resolveLocale(locale);
};

setEnableI18n = (enableI18n: boolean): void => {
this.enableI18n = enableI18n;
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { ReadonlyConditionStoreInterface } from "../i18n-manager/types";

let conditionStore: ReadonlyConditionStoreInterface | undefined;

export function createConditionStoreSingleton<
T extends ReadonlyConditionStoreInterface,
>(notInitializedMessage: string) {
function getConditionStore(): T {
/**
* TODO: each package throws a different error message
*/
if (!conditionStore) {
throw new Error(notInitializedMessage);
}
return conditionStore as T;
}

function setConditionStore(nextConditionStore: T): void {
conditionStore = nextConditionStore;
}

function isConditionStoreInitialized(): boolean {
return conditionStore !== undefined;
}

return {
getConditionStore,
setConditionStore,
isConditionStoreInitialized,
};
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { LocaleConfig } from '@generaltranslation/format';
import { libraryDefaultLocale } from 'generaltranslation/internal';
import type { ConditionStoreConfig } from '../types';
import { LocaleConfig } from "@generaltranslation/format";
import { libraryDefaultLocale } from "generaltranslation/internal";
import type { LocaleResolverConfig } from "../i18n-manager/types";

export type LocaleCandidates = string | string[] | undefined;

function normalizeConditionStoreConfig({
defaultLocale,
locales,
customMapping,
}: ConditionStoreConfig = {}) {
}: LocaleResolverConfig = {}) {
const fallbackLocale = defaultLocale || libraryDefaultLocale;
return {
defaultLocale: fallbackLocale,
Expand All @@ -26,17 +26,17 @@ type NormalizedConditionStoreConfig = ReturnType<
*/
export function determineSupportedLocale(
candidates: LocaleCandidates,
config: ConditionStoreConfig = {}
config: LocaleResolverConfig = {},
): string | undefined {
return determineSupportedLocaleWithConfig(
candidates,
normalizeConditionStoreConfig(config)
normalizeConditionStoreConfig(config),
);
}

function determineSupportedLocaleWithConfig(
candidates: LocaleCandidates,
config: NormalizedConditionStoreConfig
config: NormalizedConditionStoreConfig,
): string | undefined {
if (
candidates == null ||
Expand All @@ -54,7 +54,7 @@ function determineSupportedLocaleWithConfig(
*/
export function resolveSupportedLocale(
candidates: LocaleCandidates,
config: ConditionStoreConfig = {}
config: LocaleResolverConfig = {},
): string {
const normalizedConfig = normalizeConditionStoreConfig(config);
return (
Expand All @@ -63,7 +63,7 @@ export function resolveSupportedLocale(
);
}

export function createLocaleResolver(config: ConditionStoreConfig = {}) {
export function createLocaleResolver(config: LocaleResolverConfig = {}) {
const normalizedConfig = normalizeConditionStoreConfig(config);
return (candidates?: LocaleCandidates): string =>
determineSupportedLocaleWithConfig(candidates, normalizedConfig) ||
Expand Down
9 changes: 9 additions & 0 deletions packages/i18n/src/condition-store/singleton-operations.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { createConditionStoreSingleton } from "./createConditionStoreSingleton";
import { WritableConditionStore } from "./WritableConditionStore";

export const {
getConditionStore: getWritableConditionStore,
setConditionStore: setWritableConditionStore,
} = createConditionStoreSingleton<WritableConditionStore>(
"WritableConditionStore is not initialized.",
);
10 changes: 4 additions & 6 deletions packages/i18n/src/helpers/locale.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import {
getCurrentLocale,
getI18nManager,
} from '../i18n-manager/singleton-operations';
import { getWritableConditionStore } from "../condition-store/singleton-operations";
import { getI18nManager } from "../i18n-manager/singleton-operations";

/**
* Get the current locale
Expand All @@ -12,7 +10,7 @@ import {
* console.log(locale); // 'en-US'
*/
export function getLocale() {
return getCurrentLocale();
return getWritableConditionStore().getLocale();
}

/**
Expand Down Expand Up @@ -52,7 +50,7 @@ export function getDefaultLocale() {
* @example
* const localeProperties = getLocaleProperties('en-US');
*/
export function getLocaleProperties(locale = getCurrentLocale()) {
export function getLocaleProperties(locale = getLocale()) {
const i18nManager = getI18nManager();
const gtInstance = i18nManager.getGTClass();
return gtInstance.getLocaleProperties(locale);
Expand Down
Loading
Loading