Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion build-tools/tasks/generate-i18n-messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const sourceMessagesDir = path.resolve(sourceI18nDir, 'messages');
const targetI18nDir = path.resolve(targetPath, 'components/i18n');
const targetMessagesDir = path.resolve(targetI18nDir, 'messages');

const namespace = '@cloudscape-design/components';
const namespace = 'cloudscape-design-components';
const messagesDeclarationFile = `import { I18nProviderProps } from "../provider";
declare const messages: I18nProviderProps.Messages;
export default messages;
Expand Down
2 changes: 1 addition & 1 deletion src/i18n/__integ__/i18n.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const setupTest = (testFn: (page: BasePageObject) => Promise<void>) => {
test(
'dynamic messages are loaded correctly',
setupTest(async page => {
const text = jaStaticMessages['@cloudscape-design/components'].ja['tag-editor']['i18nStrings.addButton'][0].value;
const text = jaStaticMessages['cloudscape-design-components'].ja['tag-editor']['i18nStrings.addButton'][0].value;
await page.waitForVisible(wrapper.findAddButton().toSelector());
await expect(page.getText(wrapper.findAddButton().toSelector())).resolves.toBe(text);
})
Expand Down
9 changes: 5 additions & 4 deletions src/i18n/__tests__/i18n.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as IntlMessageFormat from 'intl-messageformat';
import { range } from 'lodash';

import { I18nProvider, I18nProviderProps } from '../../../lib/components/i18n';
import { namespace } from '../../../lib/components/i18n/context';
import { MESSAGES, TestComponent } from './test-component';

afterEach(() => {
Expand All @@ -22,7 +23,7 @@ describe('with custom "lang" on <html>', () => {
document.documentElement.lang = 'es';

const spanishMessages: I18nProviderProps.Messages = {
'@cloudscape-design/components': {
[namespace]: {
es: {
'test-component': {
topLevelString: 'Custom Spanish string',
Expand Down Expand Up @@ -67,7 +68,7 @@ it('falls back to "en" if no locale is provided', () => {

it('falls back to a less specific language tag if a string is not provided for a language', () => {
const britishEnglishMessages: I18nProviderProps.Messages = {
'@cloudscape-design/components': {
[namespace]: {
'en-GB': {
'test-component': {
topLevelString: 'Custom string - colour',
Expand Down Expand Up @@ -111,7 +112,7 @@ it("doesn't override existing strings", () => {

it('merges provided message objects in order', () => {
const messageOverride: I18nProviderProps.Messages = {
'@cloudscape-design/components': {
[namespace]: {
en: {
'test-component': {
topLevelString: 'My custom string',
Expand All @@ -131,7 +132,7 @@ it('merges provided message objects in order', () => {

it('allows nesting providers', () => {
const messageOverride: I18nProviderProps.Messages = {
'@cloudscape-design/components': {
[namespace]: {
en: {
'test-component': {
topLevelString: 'My custom string',
Expand Down
4 changes: 2 additions & 2 deletions src/i18n/__tests__/test-component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import React from 'react';

import { I18nProviderProps } from '../../../lib/components/i18n';
import { useInternalI18n } from '../../../lib/components/i18n/context';
import { namespace, useInternalI18n } from '../../../lib/components/i18n/context';

interface TestComponentProps {
topLevelString?: string;
Expand All @@ -16,7 +16,7 @@ interface TestComponentProps {
}

export const MESSAGES: I18nProviderProps.Messages = {
'@cloudscape-design/components': {
[namespace]: {
en: {
'test-component': {
topLevelString: 'top level string',
Expand Down
18 changes: 13 additions & 5 deletions src/i18n/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import React, { useContext } from 'react';

import { awsuiPluginsInternal } from '../internal/plugins/api';
import { I18nFormatArgTypes } from './messages-types';

export type CustomHandler<ReturnValue, FormatFnArgs> = (formatFn: (args: FormatFnArgs) => string) => ReturnValue;
Expand All @@ -18,13 +19,20 @@ interface InternalI18nContextProps {
format: FormatFunction;
}

export const InternalI18nContext = React.createContext<InternalI18nContextProps>({
export const namespace = 'cloudscape-design-components';

const defaultContextValue: InternalI18nContextProps = {
locale: null,
format: <T>(_namespace: string, _component: string, _key: string, provided: T) => provided,
});
};

export const InternalI18nContext = awsuiPluginsInternal.sharedReactContexts.createContext<InternalI18nContextProps>(
React,
'InternalI18nContext'
);

export function useLocale(): string | null {
return useContext(InternalI18nContext).locale;
return (useContext(InternalI18nContext) ?? defaultContextValue).locale;
}

/**
Expand Down Expand Up @@ -56,12 +64,12 @@ export interface ComponentFormatFunction<ComponentName extends StringKeyOf<I18nF
export function useInternalI18n<ComponentName extends StringKeyOf<I18nFormatArgTypes>>(
componentName: ComponentName
): ComponentFormatFunction<ComponentName> {
const { format } = useContext(InternalI18nContext);
const { format } = useContext(InternalI18nContext) ?? defaultContextValue;
return <MessageKey extends StringKeyOf<I18nFormatArgTypes[ComponentName]>, ValueType>(
key: MessageKey,
provided: ValueType,
customHandler?: CustomHandler<ValueType, I18nFormatArgTypes[ComponentName][MessageKey]>
) => {
return format('@cloudscape-design/components', componentName, key, provided, customHandler);
return format(namespace, componentName, key, provided, customHandler);
};
}
3 changes: 2 additions & 1 deletion src/i18n/testing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import React from 'react';

import { namespace } from './context';
// It's okay for import for tests, because it's internal non-user code.
// eslint-disable-next-line @cloudscape-design/components/ban-files
import { I18nProvider } from './provider';
Expand All @@ -14,7 +15,7 @@ interface TestI18nProviderProps {

export default function TestI18nProvider({ messages = {}, locale = 'en', children }: TestI18nProviderProps) {
return (
<I18nProvider locale={locale} messages={[{ '@cloudscape-design/components': { [locale]: messages } }]}>
<I18nProvider locale={locale} messages={[{ [namespace]: { [locale]: messages } }]}>
{children}
</I18nProvider>
);
Expand Down
2 changes: 2 additions & 0 deletions src/internal/plugins/controllers/shared-react-contexts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export class SharedReactContexts {
let cachedContext = contexts.get(contextName);

if (!cachedContext) {
// We cannot put a default value here, because it will be shared between versions.
// Consumers of this API must apply default value on their end.
cachedContext = ReactInstance.createContext<T>(undefined as T);
contexts.set(contextName, cachedContext);
}
Expand Down
Loading