Skip to content

Commit

Permalink
Fix #1458 improve translation support
Browse files Browse the repository at this point in the history
  • Loading branch information
mistic100 committed Oct 15, 2024
1 parent 28a51d2 commit 5453380
Show file tree
Hide file tree
Showing 16 changed files with 81 additions and 45 deletions.
2 changes: 2 additions & 0 deletions docs/guide/navbar.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ Unique identifier of the button, usefull when using the `navbar.getButton()` met

Tooltip displayed when the mouse is over the button.

For translation purposes it can be a key in the main [`lang`](./config.md#lang) object.

#### `className`

- type : `string`
Expand Down
2 changes: 2 additions & 0 deletions docs/plugins/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ settings.addSetting({
});
```

For translation purposes, both `label` can be a key in the main [`lang`](../guide/config.md#lang) object.

## Button badge

A setting can also have a `badge` function, which return value will be used as a badge on the settings button itself. **Only one setting can declare a badge.**
Expand Down
6 changes: 4 additions & 2 deletions packages/core/src/buttons/AbstractButton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ export abstract class AbstractButton extends AbstractComponent {
});

this.config = getConfig(config);
this.config.id = (this.constructor as typeof AbstractButton).id;
if (!config.id) {
this.config.id = (this.constructor as typeof AbstractButton).id;
}

if (config.icon) {
this.__setIcon(config.icon);
Expand All @@ -110,7 +112,7 @@ export abstract class AbstractButton extends AbstractComponent {
this.state.width = this.container.offsetWidth;

if (this.config.title) {
this.container.title = this.config.title;
this.container.title = this.viewer.config.lang[this.config.title] ?? this.config.title;
} else if (this.id && this.id in this.viewer.config.lang) {
this.container.title = (this.viewer.config.lang as any)[this.id];
}
Expand Down
7 changes: 1 addition & 6 deletions packages/core/src/buttons/CustomButton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export class CustomButton extends AbstractButton {

constructor(navbar: Navbar, config: NavbarCustomButton) {
super(navbar, {
id: config.id ?? `psvButton-${Math.random().toString(36).substring(2)}`,
className: `psv-custom-button ${config.className || ''}`,
hoverScale: false,
collapsable: config.collapsable !== false,
Expand All @@ -16,12 +17,6 @@ export class CustomButton extends AbstractButton {

this.customOnClick = config.onClick;

if (config.id) {
this.config.id = config.id;
} else {
this.config.id = 'psvButton-' + Math.random().toString(36).substring(2);
}

if (config.content) {
if (typeof config.content === 'string') {
this.container.innerHTML = config.content;
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ export type NavbarCustomButton = {
id?: string;
/**
* Tooltip displayed when the mouse is over the button
* If can be a key in the global `lang` config
*/
title?: string;
/**
Expand Down
5 changes: 4 additions & 1 deletion packages/map-plugin/src/components/MapCompassButton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ export class MapCompassButton extends AbstractMapButton {
constructor(map: MapComponent) {
super(map, ButtonPosition.VERTICAL);

this.container.title = this.viewer.config.lang['mapNorth'];
this.container.innerHTML = icon;
this.container.querySelector('svg').style.width = '80%';

Expand All @@ -19,4 +18,8 @@ export class MapCompassButton extends AbstractMapButton {
rotate(angle: number) {
this.container.querySelector('svg').style.transform = `rotate3d(0, 0, 1, ${-angle}rad)`;
}

override update() {
this.container.title = this.viewer.config.lang['mapNorth'];
}
}
9 changes: 9 additions & 0 deletions packages/map-plugin/src/components/MapComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export class MapComponent extends AbstractComponent {
window.addEventListener('touchend', this);
canvasContainer.addEventListener('wheel', this);
viewer.addEventListener(events.KeypressEvent.type, this);
viewer.addEventListener(events.ConfigChangedEvent.type, this);

// map canvas
this.canvas = document.createElement('canvas');
Expand Down Expand Up @@ -183,6 +184,14 @@ export class MapComponent extends AbstractComponent {
e.preventDefault();
}
break;
case events.ConfigChangedEvent.type:
if ((e as events.ConfigChangedEvent).containsOptions('lang')) {
this.resetButton?.update();
this.closeButton?.update();
this.compassButton?.update();
this.maximizeButton?.update();
}
break;
case 'mousedown': {
const event = e as MouseEvent;
this.state.mouseX = event.clientX;
Expand Down
5 changes: 4 additions & 1 deletion packages/map-plugin/src/components/MapResetButton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ export class MapResetButton extends AbstractMapButton {
constructor(map: MapComponent) {
super(map, ButtonPosition.HORIZONTAL);

this.container.title = this.viewer.config.lang['mapReset'];
this.container.innerHTML = reset;
this.container.querySelector('svg').style.width = '80%';

Expand All @@ -15,4 +14,8 @@ export class MapResetButton extends AbstractMapButton {
e.stopPropagation();
});
}

override update() {
this.container.title = this.viewer.config.lang['mapReset'];
}
}
10 changes: 10 additions & 0 deletions packages/plan-plugin/src/components/PlanComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export class PlanComponent extends AbstractComponent {
});

viewer.addEventListener(events.KeypressEvent.type, this);
viewer.addEventListener(events.ConfigChangedEvent.type, this);

const mapContainer = document.createElement('div');
mapContainer.className = 'psv-plan__container';
Expand Down Expand Up @@ -132,6 +133,7 @@ export class PlanComponent extends AbstractComponent {
cancelAnimationFrame(this.state.renderLoop);

this.viewer.removeEventListener(events.KeypressEvent.type, this);
this.viewer.removeEventListener(events.ConfigChangedEvent.type, this);

this.gallery?.removeEventListener('show-gallery', this);
this.gallery?.removeEventListener('hide-gallery', this);
Expand All @@ -150,6 +152,14 @@ export class PlanComponent extends AbstractComponent {
e.preventDefault();
}
break;
case events.ConfigChangedEvent.type:
if ((e as events.ConfigChangedEvent).containsOptions('lang')) {
this.resetButton?.update();
this.closeButton?.update();
this.layersButton?.update();
this.maximizeButton?.update();
}
break;
case 'transitionstart':
this.state.forceRender = true;
break;
Expand Down
15 changes: 9 additions & 6 deletions packages/plan-plugin/src/components/PlanLayersButton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,14 @@ export class PlanLayersButton extends AbstractPlanButton {

constructor(plan: PlanComponent) {
super(plan, ButtonPosition.VERTICAL);

const title = this.viewer.config.lang['mapLayers'];

this.container.title = title;

this.container.innerHTML = layersIcon;

this.select = document.createElement('select');
this.select.className = 'psv-plan__layers-select';
this.select.setAttribute('aria-label', title)

const placeholder = document.createElement('option');
placeholder.disabled = true;
placeholder.innerText = title;
this.select.appendChild(placeholder);

this.select.addEventListener('change', () => {
Expand All @@ -33,6 +28,14 @@ export class PlanLayersButton extends AbstractPlanButton {
this.hide();
}

override update() {
const title = this.viewer.config.lang['mapLayers'];

this.container.title = title;
this.select.setAttribute('aria-label', title);
this.select.querySelector('option').innerText = title;
}

setLayers(layers: string[]) {
this.show();

Expand Down
5 changes: 4 additions & 1 deletion packages/plan-plugin/src/components/PlanResetButton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ export class PlanResetButton extends AbstractPlanButton {
constructor(plan: PlanComponent) {
super(plan, ButtonPosition.HORIZONTAL);

this.container.title = this.viewer.config.lang['mapReset'];
this.container.innerHTML = reset;
this.container.querySelector('svg').style.width = '80%';

Expand All @@ -15,4 +14,8 @@ export class PlanResetButton extends AbstractPlanButton {
e.stopPropagation();
});
}

override update() {
this.container.title = this.viewer.config.lang['mapReset'];
}
}
2 changes: 1 addition & 1 deletion packages/resolution-plugin/src/ResolutionPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export class ResolutionPlugin extends AbstractPlugin<ResolutionPluginEvents> {
this.settings.addSetting({
id: ResolutionPlugin.id,
type: 'options',
label: this.viewer.config.lang.resolution,
label: ResolutionPlugin.id,
current: () => this.state.resolution,
options: () => this.resolutions,
apply: (resolution) => this.__setResolutionIfExists(resolution),
Expand Down
5 changes: 3 additions & 2 deletions packages/resolution-plugin/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { DEFAULTS } from '@photo-sphere-viewer/core';
import * as events from './events';
import { ResolutionPlugin } from './ResolutionPlugin';

DEFAULTS.lang.resolution = 'Quality';
DEFAULTS.lang[ResolutionPlugin.id] = 'Quality';

export { ResolutionPlugin } from './ResolutionPlugin';
export { ResolutionPlugin };
export * from './model';
export { events };
12 changes: 2 additions & 10 deletions packages/settings-plugin/src/SettingsComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,7 @@ export class SettingsComponent extends AbstractComponent {
* Shows the list of options
*/
private __showSettings(focus: boolean) {
this.container.innerHTML = SETTINGS_TEMPLATE(this.plugin.settings, (setting) => {
const current = setting.current();
const option = setting.options().find((opt) => opt.id === current);
return option?.label;
});
this.container.innerHTML = SETTINGS_TEMPLATE(this.plugin.settings, this.viewer.config.lang);

// must not focus during the initial transition
if (focus) {
Expand All @@ -153,11 +149,7 @@ export class SettingsComponent extends AbstractComponent {
* Shows setting options panel
*/
private __showOptions(setting: OptionsSetting) {
const current = setting.current();

this.container.innerHTML = SETTING_OPTIONS_TEMPLATE(setting, (option) => {
return option.id === current;
});
this.container.innerHTML = SETTING_OPTIONS_TEMPLATE(setting, this.viewer.config.lang);

this.__focusFirstOption();
}
Expand Down
38 changes: 23 additions & 15 deletions packages/settings-plugin/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { utils } from '@photo-sphere-viewer/core';
import { utils, ViewerConfig } from '@photo-sphere-viewer/core';
import check from './icons/check.svg';
import chevron from './icons/chevron.svg';
import switchOff from './icons/switch-off.svg';
import switchOn from './icons/switch-on.svg';
import { OptionsSetting, BaseSetting, SettingOption, ToggleSetting } from './model';
import { OptionsSetting, Setting, ToggleSetting } from './model';

export const LOCAL_STORAGE_KEY = 'psvSettings';
export const ID_PANEL = 'settings';
Expand All @@ -17,29 +17,33 @@ export const OPTION_DATA_KEY = utils.dasherize(OPTION_DATA);
/**
* Setting item template, by type
*/
export const SETTINGS_TEMPLATE_: Record<BaseSetting['type'], any> = {
options: (setting: OptionsSetting, optionsCurrent: (s: OptionsSetting) => string) => `
<span class="psv-settings-item-label">${setting.label}</span>
<span class="psv-settings-item-value">${optionsCurrent(setting)}</span>
export const SETTINGS_TEMPLATE_: Record<Setting['type'], any> = {
options: (setting: OptionsSetting, lang: ViewerConfig['lang']) => {
const current = setting.current();
const option = setting.options().find((opt) => opt.id === current);
return `
<span class="psv-settings-item-label">${lang[setting.label] ?? setting.label}</span>
<span class="psv-settings-item-value">${option?.label ?? current}</span>
<span class="psv-settings-item-icon">${chevron}</span>
`,
toggle: (setting: ToggleSetting) => `
<span class="psv-settings-item-label">${setting.label}</span>
`;
},
toggle: (setting: ToggleSetting, lang: ViewerConfig['lang']) => `
<span class="psv-settings-item-label">${lang[setting.label] ?? setting.label}</span>
<span class="psv-settings-item-value">${setting.active() ? switchOn : switchOff}</span>
`,
};

/**
* Settings list template
*/
export const SETTINGS_TEMPLATE = (settings: BaseSetting[], optionsCurrent: (s: OptionsSetting) => string) => `
export const SETTINGS_TEMPLATE = (settings: Setting[], lang: ViewerConfig['lang']) => `
<ul class="psv-settings-list">
${settings
.map(
(setting) => `
<li class="psv-settings-item" tabindex="0"
data-${SETTING_DATA_KEY}="${setting.id}" data-${OPTION_DATA_KEY}="${ID_ENTER}">
${SETTINGS_TEMPLATE_[setting.type](setting as OptionsSetting, optionsCurrent)}
${SETTINGS_TEMPLATE_[setting.type](setting, lang)}
</li>
`
)
Expand All @@ -50,24 +54,28 @@ export const SETTINGS_TEMPLATE = (settings: BaseSetting[], optionsCurrent: (s: O
/**
* Settings options template
*/
export const SETTING_OPTIONS_TEMPLATE = (setting: OptionsSetting, optionActive: (o: SettingOption) => boolean) => `
export const SETTING_OPTIONS_TEMPLATE = (setting: OptionsSetting, lang: ViewerConfig['lang']) => {
const current = setting.current();

return `
<ul class="psv-settings-list">
<li class="psv-settings-item psv-settings-item--header" tabindex="0"
data-${SETTING_DATA_KEY}="${setting.id}" data-${OPTION_DATA_KEY}="${ID_BACK}">
<span class="psv-settings-item-icon">${chevron}</span>
<span class="psv-settings-item-label">${setting.label}</span>
<span class="psv-settings-item-label">${lang[setting.label] ?? setting.label}</span>
</li>
${setting
.options()
.map(
(option) => `
<li class="psv-settings-item" tabindex="0"
data-${SETTING_DATA_KEY}="${setting.id}" data-${OPTION_DATA_KEY}="${option.id}">
<span class="psv-settings-item-icon">${optionActive(option) ? check : ''}</span>
<span class="psv-settings-item-value">${option.label}</span>
<span class="psv-settings-item-icon">${option.id === current ? check : ''}</span>
<span class="psv-settings-item-value">${lang[option.label] ?? option.label}</span>
</li>
`
)
.join('')}
</ul>
`;
};
2 changes: 2 additions & 0 deletions packages/settings-plugin/src/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export type BaseSetting = {
id: string;
/**
* label of the setting
* If can be a key in the global `lang` config
*/
label: string;
/**
Expand Down Expand Up @@ -64,6 +65,7 @@ export type SettingOption = {
id: string;
/**
* label of the option
* If can be a key in the global `lang` config
*/
label: string;
};
Expand Down

0 comments on commit 5453380

Please sign in to comment.