Browse Source

Temp language commit

master
Eduard Kuzmenko 3 years ago
parent
commit
945acf5df0
  1. 5
      src/components/button.ts
  2. 5
      src/components/buttonMenu.ts
  3. 9
      src/components/inputField.ts
  4. 7
      src/components/sidebarLeft/index.ts
  5. 15
      src/components/sidebarLeft/tabs/chatFolders.ts
  6. 15
      src/components/sidebarLeft/tabs/editProfile.ts
  7. 14
      src/components/sidebarLeft/tabs/settings.ts
  8. 6
      src/components/sliderTab.ts
  9. 103
      src/lib/langPack.ts

5
src/components/button.ts

@ -1,6 +1,7 @@
import { i18n, LangPackKey } from "../lib/langPack";
import { ripple } from "./ripple"; import { ripple } from "./ripple";
const Button = (className: string, options: Partial<{noRipple: true, onlyMobile: true, icon: string, rippleSquare: true, text: string, disabled: boolean}> = {}) => { const Button = (className: string, options: Partial<{noRipple: true, onlyMobile: true, icon: string, rippleSquare: true, text: LangPackKey, disabled: boolean}> = {}) => {
const button = document.createElement('button'); const button = document.createElement('button');
button.className = className + (options.icon ? ' tgico-' + options.icon : ''); button.className = className + (options.icon ? ' tgico-' + options.icon : '');
@ -21,7 +22,7 @@ const Button = (className: string, options: Partial<{noRipple: true, onlyMobile:
} }
if(options.text) { if(options.text) {
button.append(options.text); button.append(i18n(options.text));
} }
return button; return button;

5
src/components/buttonMenu.ts

@ -1,11 +1,12 @@
import { attachClickEvent, AttachClickOptions, cancelEvent, CLICK_EVENT_NAME } from "../helpers/dom"; import { attachClickEvent, AttachClickOptions, cancelEvent, CLICK_EVENT_NAME } from "../helpers/dom";
import ListenerSetter from "../helpers/listenerSetter"; import ListenerSetter from "../helpers/listenerSetter";
import { i18n, LangPackKey } from "../lib/langPack";
import { closeBtnMenu } from "./misc"; import { closeBtnMenu } from "./misc";
import { ripple } from "./ripple"; import { ripple } from "./ripple";
export type ButtonMenuItemOptions = { export type ButtonMenuItemOptions = {
icon: string, icon: string,
text: string, text: LangPackKey,
onClick: (e: MouseEvent | TouchEvent) => void, onClick: (e: MouseEvent | TouchEvent) => void,
element?: HTMLElement, element?: HTMLElement,
options?: AttachClickOptions options?: AttachClickOptions
@ -18,7 +19,7 @@ const ButtonMenuItem = (options: ButtonMenuItemOptions) => {
const {icon, text, onClick} = options; const {icon, text, onClick} = options;
const el = document.createElement('div'); const el = document.createElement('div');
el.className = 'btn-menu-item tgico-' + icon; el.className = 'btn-menu-item tgico-' + icon;
el.innerText = text; el.append(i18n(text));
ripple(el); ripple(el);

9
src/components/inputField.ts

@ -1,6 +1,7 @@
import { getRichValue, isInputEmpty } from "../helpers/dom"; import { getRichValue, isInputEmpty } from "../helpers/dom";
import { debounce } from "../helpers/schedulers"; import { debounce } from "../helpers/schedulers";
import { checkRTL } from "../helpers/string"; import { checkRTL } from "../helpers/string";
import { i18n_, LangPackKey } from "../lib/langPack";
import RichTextProcessor from "../lib/richtextprocessor"; import RichTextProcessor from "../lib/richtextprocessor";
let init = () => { let init = () => {
@ -59,7 +60,7 @@ export enum InputState {
export type InputFieldOptions = { export type InputFieldOptions = {
placeholder?: string, placeholder?: string,
label?: string, label?: LangPackKey,
name?: string, name?: string,
maxLength?: number, maxLength?: number,
showLengthOn?: number, showLengthOn?: number,
@ -97,7 +98,6 @@ class InputField {
this.container.innerHTML = ` this.container.innerHTML = `
<div ${placeholder ? `data-placeholder="${placeholder}"` : ''} contenteditable="true" class="input-field-input"></div> <div ${placeholder ? `data-placeholder="${placeholder}"` : ''} contenteditable="true" class="input-field-input"></div>
${label ? `<label>${label}</label>` : ''}
`; `;
input = this.container.firstElementChild as HTMLElement; input = this.container.firstElementChild as HTMLElement;
@ -135,7 +135,6 @@ class InputField {
} else { } else {
this.container.innerHTML = ` this.container.innerHTML = `
<input type="text" ${name ? `name="${name}"` : ''} ${placeholder ? `placeholder="${placeholder}"` : ''} autocomplete="off" ${label ? 'required=""' : ''} class="input-field-input"> <input type="text" ${name ? `name="${name}"` : ''} ${placeholder ? `placeholder="${placeholder}"` : ''} autocomplete="off" ${label ? 'required=""' : ''} class="input-field-input">
${label ? `<label>${label}</label>` : ''}
`; `;
input = this.container.firstElementChild as HTMLElement; input = this.container.firstElementChild as HTMLElement;
@ -143,7 +142,9 @@ class InputField {
} }
if(label) { if(label) {
this.label = this.container.lastElementChild as HTMLLabelElement; this.label = document.createElement('label');
i18n_({element: this.label, key: label});
this.container.append(this.label);
} }
let processInput: () => void; let processInput: () => void;

7
src/components/sidebarLeft/index.ts

@ -23,6 +23,7 @@ import AppNewChannelTab from "./tabs/newChannel";
import AppContactsTab from "./tabs/contacts"; import AppContactsTab from "./tabs/contacts";
import AppArchivedTab from "./tabs/archivedTab"; import AppArchivedTab from "./tabs/archivedTab";
import AppAddMembersTab from "./tabs/addMembers"; import AppAddMembersTab from "./tabs/addMembers";
import { i18n_, LangPackKey } from "../../lib/langPack";
export const LEFT_COLUMN_ACTIVE_CLASSNAME = 'is-left-column-shown'; export const LEFT_COLUMN_ACTIVE_CLASSNAME = 'is-left-column-shown';
@ -413,7 +414,7 @@ export class SettingSection {
public caption: HTMLElement; public caption: HTMLElement;
constructor(options: { constructor(options: {
name?: string, name?: LangPackKey,
caption?: string, caption?: string,
noDelimiter?: boolean noDelimiter?: boolean
}) { }) {
@ -432,7 +433,7 @@ export class SettingSection {
if(options.name) { if(options.name) {
this.title = document.createElement('div'); this.title = document.createElement('div');
this.title.classList.add('sidebar-left-h2', 'sidebar-left-section-name'); this.title.classList.add('sidebar-left-h2', 'sidebar-left-section-name');
this.title.innerHTML = options.name; i18n_({element: this.title, key: options.name});
this.content.append(this.title); this.content.append(this.title);
} }
@ -451,7 +452,7 @@ export class SettingSection {
} }
} }
export const generateSection = (appendTo: Scrollable, name?: string, caption?: string) => { export const generateSection = (appendTo: Scrollable, name?: LangPackKey, caption?: string) => {
const section = new SettingSection({name, caption}); const section = new SettingSection({name, caption});
appendTo.append(section.container); appendTo.append(section.container);
return section.content; return section.content;

15
src/components/sidebarLeft/tabs/chatFolders.ts

@ -16,6 +16,7 @@ import rootScope from "../../../lib/rootScope";
import AppEditFolderTab from "./editFolder"; import AppEditFolderTab from "./editFolder";
import Row from "../../row"; import Row from "../../row";
import { SettingSection } from ".."; import { SettingSection } from "..";
import { i18n_ } from "../../../lib/langPack";
export default class AppChatFoldersTab extends SliderSuperTab { export default class AppChatFoldersTab extends SliderSuperTab {
private createFolderBtn: HTMLElement; private createFolderBtn: HTMLElement;
@ -101,7 +102,7 @@ export default class AppChatFoldersTab extends SliderSuperTab {
protected init() { protected init() {
this.container.classList.add('chat-folders-container'); this.container.classList.add('chat-folders-container');
this.title.innerText = 'Chat Folders'; this.setTitle('ChatList.Filter.List.Title');
this.scrollable.container.classList.add('chat-folders'); this.scrollable.container.classList.add('chat-folders');
@ -110,20 +111,20 @@ export default class AppChatFoldersTab extends SliderSuperTab {
const caption = document.createElement('div'); const caption = document.createElement('div');
caption.classList.add('caption'); caption.classList.add('caption');
caption.innerHTML = `Create folders for different groups of chats<br>and quickly switch between them.`; i18n_({element: caption, key: 'ChatList.Filter.Header'});
this.createFolderBtn = Button('btn-primary btn-color-primary btn-create-folder', { this.createFolderBtn = Button('btn-primary btn-color-primary btn-create-folder', {
text: 'Create Folder', text: 'ChatList.Filter.NewTitle',
icon: 'add' icon: 'add'
}); });
this.foldersSection = new SettingSection({ this.foldersSection = new SettingSection({
name: 'Folders' name: 'ChatList.Filter.List.Header'
}); });
this.foldersSection.container.style.display = 'none'; this.foldersSection.container.style.display = 'none';
this.suggestedSection = new SettingSection({ this.suggestedSection = new SettingSection({
name: 'Recommended folders' name: 'ChatList.Filter.Recommended.Header'
}); });
this.suggestedSection.container.style.display = 'none'; this.suggestedSection.container.style.display = 'none';
@ -207,9 +208,7 @@ export default class AppChatFoldersTab extends SliderSuperTab {
suggestedFilters.forEach(filter => { suggestedFilters.forEach(filter => {
const div = this.renderFolder(filter); const div = this.renderFolder(filter);
const button = document.createElement('button'); const button = Button('btn-primary btn-color-primary', {text: 'ChatList.Filter.Recommended.Add'});
button.classList.add('btn-primary', 'btn-color-primary');
button.innerText = 'Add';
div.append(button); div.append(button);
this.suggestedSection.content.append(div); this.suggestedSection.content.append(div);

15
src/components/sidebarLeft/tabs/editProfile.ts

@ -5,6 +5,7 @@ import { SliderSuperTab } from "../../slider";
import { attachClickEvent } from "../../../helpers/dom"; import { attachClickEvent } from "../../../helpers/dom";
import EditPeer from "../../editPeer"; import EditPeer from "../../editPeer";
import { UsernameInputField } from "../../usernameInputField"; import { UsernameInputField } from "../../usernameInputField";
import { i18n_ } from "../../../lib/langPack";
// TODO: аватарка не поменяется в этой вкладке после изменения почему-то (если поставить в другом клиенте, и потом тут проверить, для этого ещё вышел в чатлист) // TODO: аватарка не поменяется в этой вкладке после изменения почему-то (если поставить в другом клиенте, и потом тут проверить, для этого ещё вышел в чатлист)
@ -21,7 +22,7 @@ export default class AppEditProfileTab extends SliderSuperTab {
protected async init() { protected async init() {
this.container.classList.add('edit-profile-container'); this.container.classList.add('edit-profile-container');
this.title.innerText = 'Edit Profile'; this.setTitle('EditAccount.Title');
const inputFields: InputField[] = []; const inputFields: InputField[] = [];
@ -30,17 +31,17 @@ export default class AppEditProfileTab extends SliderSuperTab {
inputWrapper.classList.add('input-wrapper'); inputWrapper.classList.add('input-wrapper');
this.firstNameInputField = new InputField({ this.firstNameInputField = new InputField({
label: 'Name', label: 'Login.Register.FirstName.Placeholder',
name: 'first-name', name: 'first-name',
maxLength: 70 maxLength: 70
}); });
this.lastNameInputField = new InputField({ this.lastNameInputField = new InputField({
label: 'Last Name', label: 'Login.Register.LastName.Placeholder',
name: 'last-name', name: 'last-name',
maxLength: 64 maxLength: 64
}); });
this.bioInputField = new InputField({ this.bioInputField = new InputField({
label: 'Bio (optional)', label: 'AccountSettings.Bio',
name: 'bio', name: 'bio',
maxLength: 70 maxLength: 70
}); });
@ -49,7 +50,7 @@ export default class AppEditProfileTab extends SliderSuperTab {
const caption = document.createElement('div'); const caption = document.createElement('div');
caption.classList.add('caption'); caption.classList.add('caption');
caption.innerHTML = 'Any details such as age, occupation or city. Example:<br>23 y.o. designer from San Francisco.'; i18n_({element: caption, key: 'Bio.Description'});
inputFields.push(this.firstNameInputField, this.lastNameInputField, this.bioInputField); inputFields.push(this.firstNameInputField, this.lastNameInputField, this.bioInputField);
this.scrollable.append(inputWrapper, caption); this.scrollable.append(inputWrapper, caption);
@ -68,14 +69,14 @@ export default class AppEditProfileTab extends SliderSuperTab {
{ {
const h2 = document.createElement('div'); const h2 = document.createElement('div');
h2.classList.add('sidebar-left-h2'); h2.classList.add('sidebar-left-h2');
h2.innerText = 'Username'; i18n_({element: h2, key: 'EditAccount.Username'});
const inputWrapper = document.createElement('div'); const inputWrapper = document.createElement('div');
inputWrapper.classList.add('input-wrapper'); inputWrapper.classList.add('input-wrapper');
this.usernameInputField = new UsernameInputField({ this.usernameInputField = new UsernameInputField({
peerId: 0, peerId: 0,
label: 'Username (optional)', label: 'EditAccount.Username',
name: 'username', name: 'username',
plainText: true, plainText: true,
listenerSetter: this.listenerSetter, listenerSetter: this.listenerSetter,

14
src/components/sidebarLeft/tabs/settings.ts

@ -32,7 +32,7 @@ export default class AppSettingsTab extends SliderSuperTab {
const btnMenu = ButtonMenuToggle({}, 'bottom-left', [{ const btnMenu = ButtonMenuToggle({}, 'bottom-left', [{
icon: 'logout', icon: 'logout',
text: 'Log Out', text: 'EditAccount.Logout',
onClick: () => { onClick: () => {
apiManager.logOut(); apiManager.logOut();
} }
@ -96,12 +96,12 @@ export default class AppSettingsTab extends SliderSuperTab {
buttonsDiv.classList.add('profile-buttons'); buttonsDiv.classList.add('profile-buttons');
const className = 'profile-button btn-primary btn-transparent'; const className = 'profile-button btn-primary btn-transparent';
buttonsDiv.append(this.buttons.edit = Button(className, {icon: 'edit', text: 'Edit Profile'})); buttonsDiv.append(this.buttons.edit = Button(className, {icon: 'edit', text: 'EditAccount.Title'}));
buttonsDiv.append(this.buttons.folders = Button(className, {icon: 'folder', text: 'Chat Folders'})); buttonsDiv.append(this.buttons.folders = Button(className, {icon: 'folder', text: 'AccountSettings.Filters'}));
buttonsDiv.append(this.buttons.general = Button(className, {icon: 'settings', text: 'General Settings'})); buttonsDiv.append(this.buttons.general = Button(className, {icon: 'settings', text: 'Telegram.GeneralSettingsViewController'}));
buttonsDiv.append(this.buttons.notifications = Button(className, {icon: 'unmute', text: 'Notifications'})); buttonsDiv.append(this.buttons.notifications = Button(className, {icon: 'unmute', text: 'AccountSettings.Notifications'}));
buttonsDiv.append(this.buttons.privacy = Button(className, {icon: 'lock', text: 'Privacy and Security'})); buttonsDiv.append(this.buttons.privacy = Button(className, {icon: 'lock', text: 'AccountSettings.PrivacyAndSecurity'}));
buttonsDiv.append(this.buttons.language = Button(className, {icon: 'language', text: 'Language', disabled: true})); buttonsDiv.append(this.buttons.language = Button(className, {icon: 'language', text: 'AccountSettings.Language'}));
this.scrollable.append(this.avatarElem, this.nameDiv, this.phoneDiv, buttonsDiv); this.scrollable.append(this.avatarElem, this.nameDiv, this.phoneDiv, buttonsDiv);
this.scrollable.container.classList.add('profile-content-wrapper'); this.scrollable.container.classList.add('profile-content-wrapper');

6
src/components/sliderTab.ts

@ -1,5 +1,6 @@
import EventListenerBase from "../helpers/eventListenerBase"; import EventListenerBase from "../helpers/eventListenerBase";
import ListenerSetter from "../helpers/listenerSetter"; import ListenerSetter from "../helpers/listenerSetter";
import { i18n, LangPackKey } from "../lib/langPack";
import ButtonIcon from "./buttonIcon"; import ButtonIcon from "./buttonIcon";
import Scrollable from "./scrollable"; import Scrollable from "./scrollable";
import SidebarSlider from "./slider"; import SidebarSlider from "./slider";
@ -92,6 +93,11 @@ export default class SliderSuperTab implements SliderTab {
this.listenerSetter.removeAll(); this.listenerSetter.removeAll();
} }
} }
protected setTitle(key: LangPackKey) {
this.title.innerHTML = '';
this.title.append(i18n(key));
}
} }
export class SliderSuperTabEventable extends SliderSuperTab { export class SliderSuperTabEventable extends SliderSuperTab {

103
src/lib/langPack.ts

@ -1,3 +1,4 @@
import { MOUNT_CLASS_TO } from "../config/debug";
import { LangPackString } from "../layer"; import { LangPackString } from "../layer";
import apiManager from "./mtproto/mtprotoworker"; import apiManager from "./mtproto/mtprotoworker";
@ -31,8 +32,26 @@ export const langPack: {[actionType: string]: string} = {
"messageActionBotAllowed": "You allowed this bot to message you when logged in {}" "messageActionBotAllowed": "You allowed this bot to message you when logged in {}"
}; };
export namespace Internationalization { namespace Strings {
let strings: {[key: string]: LangPackString} = {}; export type Bio = 'Bio.Description';
export type LoginRegister = 'Login.Register.FirstName.Placeholder' | 'Login.Register.LastName.Placeholder';
export type EditAccount = 'EditAccount.Logout' | 'EditAccount.Title' | 'EditAccount.Title' | 'EditAccount.Username';
export type AccountSettings = 'AccountSettings.Filters' | 'AccountSettings.Notifications' | 'AccountSettings.PrivacyAndSecurity' | 'AccountSettings.Language' | 'AccountSettings.Bio';
export type Telegram = 'Telegram.GeneralSettingsViewController';
export type ChatFilters = 'ChatList.Filter.Header' | 'ChatList.Filter.NewTitle' | 'ChatList.Filter.List.Header' | 'ChatList.Filter.Recommended.Header' | 'ChatList.Filter.Recommended.Add' | 'ChatList.Filter.List.Title';
export type LangPackKey = AccountSettings | EditAccount | Telegram | ChatFilters | LoginRegister | Bio | string;
}
export type LangPackKey = Strings.LangPackKey;
namespace I18n {
let strings: Partial<{[key in LangPackKey]: LangPackString}> = {};
export function getLangPack(langCode: string) { export function getLangPack(langCode: string) {
return apiManager.invokeApi('langpack.getLangPack', { return apiManager.invokeApi('langpack.getLangPack', {
@ -41,14 +60,86 @@ export namespace Internationalization {
}).then(langPack => { }).then(langPack => {
strings = {}; strings = {};
for(const string of langPack.strings) { for(const string of langPack.strings) {
strings[string.key] = string; strings[string.key as LangPackKey] = string;
}
const elements = Array.from(document.querySelectorAll(`.i18n`)) as HTMLElement[];
elements.forEach(element => {
const instance = weakMap.get(element);
if(instance) {
instance.update();
} }
}); });
});
} }
export function _(key: keyof typeof strings, ...args: any[]) { export function getString(key: LangPackKey, args?: any[]) {
let str = strings[key]; const str = strings[key];
let out = '';
return str; if(str) {
if(str._ === 'langPackStringPluralized') {
out = str.one_value;
} else if(str._ === 'langPackString') {
out = str.value;
} else {
out = '[' + key + ']';
} }
} else {
out = '[' + key + ']';
} }
return out;
}
const weakMap: WeakMap<HTMLElement, IntlElement> = new WeakMap();
export type IntlElementOptions = {
element?: HTMLElement,
property?: 'innerHTML' | 'placeholder'
key: LangPackKey,
args?: any[]
};
export class IntlElement {
public element: IntlElementOptions['element'];
public key: IntlElementOptions['key'];
public args: IntlElementOptions['args'];
public property: IntlElementOptions['property'] = 'innerHTML';
constructor(options: IntlElementOptions) {
this.element = options.element || document.createElement('span');
this.element.classList.add('i18n');
this.update(options);
weakMap.set(this.element, this);
}
public update(options?: IntlElementOptions) {
if(options) {
Object.assign(this, options);
}
(this.element as any)[this.property] = getString(this.key, this.args);
}
}
export function i18n(key: LangPackKey, args?: any[]) {
return new IntlElement({key, args}).element;
}
export function i18n_(options: IntlElementOptions) {
return new IntlElement(options).element;
}
}
export {I18n};
export default I18n;
const i18n = I18n.i18n;
export {i18n};
const i18n_ = I18n.i18n_;
export {i18n_};
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.I18n = I18n);

Loading…
Cancel
Save