Skip to content

Commit

Permalink
[gem-book] <gem-route> support localize
Browse files Browse the repository at this point in the history
  • Loading branch information
mantou132 committed Jan 3, 2024
1 parent ca27049 commit d64552e
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 14 deletions.
26 changes: 26 additions & 0 deletions packages/gem-examples/src/i18n/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { GemElement, html, connectStore, customElement, render } from '@mantou/gem';
import { I18n } from '@mantou/gem/helper/i18n';
import type { RouteItem } from 'duoyun-ui/elements/route';

import 'duoyun-ui/elements/route';
import '../elements/layout';

const en = {
Expand Down Expand Up @@ -29,6 +31,27 @@ const i18nModule = i18n.createSubModule<typeof en>('test', {
zh: 'data:text/plain;base64,eyJ0aXRsZSI6Iui/meaYr0kxOG4ifQ==',
});

const localizeRoutes: RouteItem[] = [
{
pattern: 'en',
getContent() {
return html`en element`;
},
},
{
pattern: 'de',
getContent() {
return html`de element`;
},
},
{
pattern: '*',
getContent() {
return html`other element`;
},
},
];

@connectStore(i18n.store)
@connectStore(i18nModule.store)
@customElement('app-root')
Expand All @@ -48,6 +71,9 @@ export class App extends GemElement {
<p>${i18nModule.get('title')}</p>
<p>${i18nModule.get('hello', 'World', 'reverse')}</p>
<p>${i18nModule.get('detail', (s) => html`<a href="#">${s}</a>`)}</p>
<h2>localize content</h2>
<dy-route .trigger=${i18n} .routes=${localizeRoutes}></dy-route>
`;
}
}
Expand Down
22 changes: 20 additions & 2 deletions packages/gem/docs/en/001-guide/002-advance/005-i18n.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ const i18n = new I18n({
},
});

html`Hello, ${i18n.get('hello', 'World', 'reverse')}`;
html`${i18n.get('hello', 'World', 'reverse')}`;

// Hello, World! reverse=> World, Hello!
```
Expand All @@ -94,7 +94,7 @@ const i18n = new I18n({
},
});

html`Hello, ${i18n.get('detail', (s) => html`<a href="#">${s}</a>`)}`;
html`${i18n.get('detail', (s) => html`<a href="#">${s}</a>`)}`;
```

## Language specified in URL
Expand Down Expand Up @@ -147,6 +147,24 @@ const i18n = new I18n({
`I18n.createSubModule` creates sub-modules, you can split language packages by route to speed up the rendering of the first screen.
## Localize
You can use `<gem-route>` to render different content according to different languages. You only need to specify the `trigger` to `i18n`:
```js
const localizeRoutes = [
{
pattern: 'zh-*',
async getContent() {
import('...');
return html`other element`;
},
},
];
html`<gem-route .trigger=${i18n} .routes=${localizeRoutes}></gem-route>`;
```
## Example

<gbp-raw src="https://raw.githubusercontent.com/mantou132/gem/master/packages/gem-examples/src/i18n/index.ts"></gbp-raw>
24 changes: 21 additions & 3 deletions packages/gem/docs/zh/001-guide/002-advance/005-i18n.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ const i18n = new I18n({
},
});

html`Hello, ${i18n.get('hello', 'World', 'reverse')}`;
html`${i18n.get('hello', 'World', 'reverse')}`;

// Hello, World! reverse=> World, Hello!
```
Expand All @@ -94,7 +94,7 @@ const i18n = new I18n({
},
});

html`Hello, ${i18n.get('detail', (s) => html`<a href="#">${s}</a>`)}`;
html`${i18n.get('detail', (s) => html`<a href="#">${s}</a>`)}`;
```

## URL 中指定语言
Expand Down Expand Up @@ -145,7 +145,25 @@ const i18n = new I18n({
## 子模块
`I18n.createSubModule` 创建子模块,你可以按路由分割语言包,加快首屏渲染速度
`I18n.createSubModule` 创建子模块,你可以按路由分割语言包,加快首屏渲染速度。
## 本地化
可以使用 `<gem-route>` 根据不同语言渲染不同的内容,只需要将 `trigger` 指定为 `i18n` 并即可,例如:
```js
const localizeRoutes = [
{
pattern: 'zh-*',
async getContent() {
import('...');
return html`other element`;
},
},
];
html`<gem-route .trigger=${i18n} .routes=${localizeRoutes}></gem-route>`;
```
## 例子

Expand Down
32 changes: 25 additions & 7 deletions packages/gem/src/elements/base/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { GemElement, html, TemplateResult } from '../../lib/element';
import { property, connectStore, emitter, Emitter, boolattribute } from '../../lib/decorators';
import { createStore, updateStore, Store } from '../../lib/store';
import { property, emitter, Emitter, boolattribute } from '../../lib/decorators';
import { createStore, updateStore, Store, connect } from '../../lib/store';
import { titleStore, history, UpdateHistoryParams } from '../../lib/history';
import { QueryString } from '../../lib/utils';

Expand Down Expand Up @@ -111,13 +111,18 @@ type State = {
content?: TemplateResult;
};

export type RouteTrigger = {
store: Store<any>;
replace: (arg: { path: string }) => void;
getParams: () => { path: string; query: any };
};

/**
* @attr inert 暂停路由更新
* @fires routechange
* @fires error
* @fires loading
*/
@connectStore(history.store)
export class GemRouteElement extends GemElement<State> {
@boolattribute transition: boolean;
@property routes?: RouteItem[] | RoutesObject;
Expand All @@ -134,6 +139,8 @@ export class GemRouteElement extends GemElement<State> {
@emitter loading: Emitter<RouteItem>;
@emitter error: Emitter<any>;

@property trigger: RouteTrigger = history;

/**当前使用的路由对象 */
currentRoute: RouteItem | null;
/**当前匹配的路由的 params */
Expand Down Expand Up @@ -209,6 +216,12 @@ export class GemRouteElement extends GemElement<State> {
};

mounted() {
this.effect(
// 触发 this.#update
() => connect(this.trigger.store, () => this.setState({})),
() => [this.trigger],
);

this.effect(
([key, path], old) => {
// 只有查询参数改变
Expand All @@ -218,7 +231,10 @@ export class GemRouteElement extends GemElement<State> {
}
this.update();
},
() => [this.key, history.getParams().path, location.search],
() => {
const { path, query } = this.trigger.getParams();
return [this.key, path + query];
},
);
}

Expand All @@ -243,13 +259,15 @@ export class GemRouteElement extends GemElement<State> {
}

update = () => {
const { route, params = {} } = GemRouteElement.findRoute(this.routes, history.getParams().path);
const { route, params = {} } = GemRouteElement.findRoute(this.routes, this.trigger.getParams().path);
const { redirect, content, getContent } = route || {};
if (redirect) {
history.replace({ path: redirect });
this.trigger.replace({ path: redirect });
return;
}
updateStore(titleStore, { title: route?.title });
if (this.trigger === history) {
updateStore(titleStore, { title: route?.title });
}
const contentOrLoader = content || getContent?.(params);
if (contentOrLoader instanceof Promise) {
this.loading(route!);
Expand Down
9 changes: 8 additions & 1 deletion packages/gem/src/helper/i18n.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { createStore, updateStore, Store } from '../lib/store';
import { html, TemplateResult } from '../lib/element';
import { GemError } from '../lib/utils';
import type { RouteTrigger } from '../elements/base/route';

import { logger } from './logger';

Expand Down Expand Up @@ -61,7 +62,7 @@ interface I18nOptions<T> {
onChange?: (currentLanguage: string) => void;
}

export class I18n<T = Record<string, Msg>> {
export class I18n<T = Record<string, Msg>> implements RouteTrigger {
resources: Resources<T>;
fallbackLanguage: string;
currentLanguage: string;
Expand All @@ -73,6 +74,12 @@ export class I18n<T = Record<string, Msg>> {

store: Store<any>;

replace = ({ path }: { path: string }) => {
this.setLanguage(path);
};

getParams = () => ({ path: this.currentLanguage, query: '' });

get #cacheCurrentKey() {
return `${this.cachePrefix}:current`;
}
Expand Down
3 changes: 2 additions & 1 deletion packages/gem/src/lib/element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,8 @@ export abstract class GemElement<T = Record<string, unknown>> extends HTMLElemen

/**
* @helper
* 在 `render` 前执行回调,和 `effect` 一样接受依赖数组参数,在 `constructor`/`willMount` 中使用;
* 在 `render` 前执行回调,不要在里面使用 `setState`
* 和 `effect` 一样接受依赖数组参数,在 `constructor`/`willMount` 中使用;
* 第一次执行时 `oldDeps` 为空
*
* ```js
Expand Down

0 comments on commit d64552e

Please sign in to comment.