Browse Source

Temp language commit

master
Eduard Kuzmenko 4 years ago
parent
commit
18734bc5aa
  1. 2
      src/components/appNavigationController.ts
  2. 23
      src/components/chat/input.ts
  3. 14
      src/components/chat/markupTooltip.ts
  4. 15
      src/components/chat/selection.ts
  5. 8
      src/components/checkboxField.ts
  6. 5
      src/components/radioField.ts
  7. 17
      src/components/row.ts
  8. 7
      src/components/sidebarLeft/index.ts
  9. 8
      src/components/sidebarLeft/tabs/background.ts
  10. 55
      src/components/sidebarLeft/tabs/chatFolders.ts
  11. 19
      src/components/sidebarLeft/tabs/editFolder.ts
  12. 16
      src/components/sidebarLeft/tabs/editProfile.ts
  13. 47
      src/components/sidebarLeft/tabs/generalSettings.ts
  14. 12
      src/components/sidebarLeft/tabs/includedChats.ts
  15. 26
      src/components/sidebarLeft/tabs/notifications.ts
  16. 52
      src/components/sidebarLeft/tabs/privacyAndSecurity.ts
  17. 140
      src/lang.ts
  18. 20
      src/lib/appManagers/appImManager.ts
  19. 96
      src/lib/langPack.ts

2
src/components/appNavigationController.ts

@ -5,7 +5,7 @@ import { logger } from "../lib/logger"; @@ -5,7 +5,7 @@ import { logger } from "../lib/logger";
import { doubleRaf } from "../helpers/schedulers";
export type NavigationItem = {
type: 'left' | 'right' | 'im' | 'chat' | 'popup' | 'media' | 'menu' | 'esg',
type: 'left' | 'right' | 'im' | 'chat' | 'popup' | 'media' | 'menu' | 'esg' | 'multiselect' | 'input-helper' | 'markup',
onPop: (canAnimate: boolean) => boolean | void,
onEscape?: () => boolean,
noHistory?: boolean,

23
src/components/chat/input.ts

@ -36,6 +36,8 @@ import rootScope from '../../lib/rootScope'; @@ -36,6 +36,8 @@ import rootScope from '../../lib/rootScope';
import PopupPinMessage from '../popups/unpinMessage';
import { debounce } from '../../helpers/schedulers';
import { tsNow } from '../../helpers/date';
import appNavigationController from '../appNavigationController';
import { isMobile } from '../../helpers/userAgent';
const RECORD_MIN_TIME = 500;
const POSTING_MEDIA_NOT_ALLOWED = 'Posting media content isn\'t allowed in this group.';
@ -1159,8 +1161,10 @@ export default class ChatInput { @@ -1159,8 +1161,10 @@ export default class ChatInput {
}
};
private onHelperCancel = (e: Event) => {
cancelEvent(e);
private onHelperCancel = (e?: Event) => {
if(e) {
cancelEvent(e);
}
if(this.willSendWebPage) {
const lastUrl = this.lastUrl;
@ -1458,7 +1462,11 @@ export default class ChatInput { @@ -1458,7 +1462,11 @@ export default class ChatInput {
this.forwardingFromPeerId = 0;
this.editMsgId = undefined;
this.helperType = this.helperFunc = undefined;
this.chat.container.classList.remove('is-helper-active');
if(this.chat.container.classList.contains('is-helper-active')) {
appNavigationController.removeByType('input-helper');
this.chat.container.classList.remove('is-helper-active');
}
}
public setInputValue(value: string, clear = true, focus = true) {
@ -1488,6 +1496,15 @@ export default class ChatInput { @@ -1488,6 +1496,15 @@ export default class ChatInput {
scroll.scrollTo(scroll.scrollHeight, 'top', true, true, 200);
} */
if(!isMobile) {
appNavigationController.pushItem({
type: 'input-helper',
onPop: () => {
this.onHelperCancel();
}
});
}
if(input !== undefined) {
this.setInputValue(input);
}

14
src/components/chat/markupTooltip.ts

@ -4,7 +4,8 @@ import RichTextProcessor from "../../lib/richtextprocessor"; @@ -4,7 +4,8 @@ import RichTextProcessor from "../../lib/richtextprocessor";
import ButtonIcon from "../buttonIcon";
import { clamp } from "../../helpers/number";
import { isTouchSupported } from "../../helpers/touchSupport";
import { isApple } from "../../helpers/userAgent";
import { isApple, isMobile } from "../../helpers/userAgent";
import appNavigationController from "../appNavigationController";
//import { logger } from "../../lib/logger";
export default class MarkupTooltip {
@ -185,6 +186,8 @@ export default class MarkupTooltip { @@ -185,6 +186,8 @@ export default class MarkupTooltip {
document.removeEventListener('mouseup', this.onMouseUpSingle);
this.waitingForMouseUp = false;
appNavigationController.removeByType('markup');
if(this.hideTimeout) clearTimeout(this.hideTimeout);
this.hideTimeout = window.setTimeout(() => {
this.hideTimeout = undefined;
@ -295,6 +298,15 @@ export default class MarkupTooltip { @@ -295,6 +298,15 @@ export default class MarkupTooltip {
this.container.classList.add('is-visible');
if(!isMobile) {
appNavigationController.pushItem({
type: 'markup',
onPop: () => {
this.hide();
}
});
}
//this.log('selection', selectionRect, activeButton);
}

15
src/components/chat/selection.ts

@ -13,6 +13,8 @@ import { toast } from "../toast"; @@ -13,6 +13,8 @@ import { toast } from "../toast";
import SetTransition from "../singleTransition";
import ListenerSetter from "../../helpers/listenerSetter";
import PopupSendNow from "../popups/sendNow";
import appNavigationController from "../appNavigationController";
import { isMobileSafari } from "../../helpers/userAgent";
const MAX_SELECTION_LENGTH = 100;
//const MIN_CLICK_MOVE = 32; // minimum bubble height
@ -315,6 +317,19 @@ export default class ChatSelection { @@ -315,6 +317,19 @@ export default class ChatSelection {
});
});
if(!isMobileSafari) {
if(forwards) {
appNavigationController.pushItem({
type: 'multiselect',
onPop: () => {
this.cancelSelection();
}
});
} else {
appNavigationController.removeByType('multiselect');
}
}
//const chatInput = this.appImManager.chatInput;
if(this.isSelecting) {

8
src/components/checkboxField.ts

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
import appStateManager from "../lib/appManagers/appStateManager";
import { getDeepProperty } from "../helpers/object";
import { ripple } from "./ripple";
import { LangPackKey, _i18n } from "../lib/langPack";
export default class CheckboxField {
public input: HTMLInputElement;
@ -8,7 +9,7 @@ export default class CheckboxField { @@ -8,7 +9,7 @@ export default class CheckboxField {
public span: HTMLSpanElement;
constructor(options: {
text?: string,
text?: LangPackKey,
name?: string,
round?: boolean,
stateKey?: string,
@ -56,10 +57,7 @@ export default class CheckboxField { @@ -56,10 +57,7 @@ export default class CheckboxField {
if(options.text) {
span = this.span = document.createElement('span');
span.classList.add('checkbox-caption');
if(options.text) {
span.innerText = options.text;
}
_i18n(span, options.text);
} else {
label.classList.add('checkbox-without-caption');
}

5
src/components/radioField.ts

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
import appStateManager from "../lib/appManagers/appStateManager";
import { getDeepProperty } from "../helpers/object";
import { LangPackKey, _i18n } from "../lib/langPack";
export default class RadioField {
public input: HTMLInputElement;
@ -7,7 +8,7 @@ export default class RadioField { @@ -7,7 +8,7 @@ export default class RadioField {
public main: HTMLElement;
constructor(options: {
text?: string,
text?: LangPackKey,
name: string,
value?: string,
stateKey?: string
@ -37,7 +38,7 @@ export default class RadioField { @@ -37,7 +38,7 @@ export default class RadioField {
main.classList.add('radio-field-main');
if(options.text) {
main.innerHTML = options.text;
_i18n(main, options.text);
/* const caption = document.createElement('div');
caption.classList.add('radio-field-main-caption');
caption.innerHTML = text;

17
src/components/row.ts

@ -3,6 +3,7 @@ import RadioField from "./radioField"; @@ -3,6 +3,7 @@ import RadioField from "./radioField";
import { ripple } from "./ripple";
import { SliderSuperTab } from "./slider";
import RadioForm from "./radioForm";
import { LangPackKey, _i18n } from "../lib/langPack";
export default class Row {
public container: HTMLElement;
@ -17,10 +18,12 @@ export default class Row { @@ -17,10 +18,12 @@ export default class Row {
constructor(options: Partial<{
icon: string,
subtitle: string,
subtitleLangKey: LangPackKey
radioField: Row['radioField'],
checkboxField: Row['checkboxField'],
noCheckboxSubtitle: boolean,
title: string,
titleLangKey: LangPackKey,
titleRight: string,
clickable: boolean | ((e: Event) => void),
navigationTab: SliderSuperTab
@ -32,6 +35,8 @@ export default class Row { @@ -32,6 +35,8 @@ export default class Row {
this.subtitle.classList.add('row-subtitle');
if(options.subtitle) {
this.subtitle.innerHTML = options.subtitle;
} else if(options.subtitleLangKey) {
_i18n(this.subtitle, options.subtitleLangKey);
}
let havePadding = false;
@ -48,7 +53,7 @@ export default class Row { @@ -48,7 +53,7 @@ export default class Row {
if(!options.noCheckboxSubtitle) {
this.checkboxField.input.addEventListener('change', () => {
this.subtitle.innerHTML = this.checkboxField.input.checked ? 'Enabled' : 'Disabled';
_i18n(this.subtitle, this.checkboxField.input.checked ? 'Checkbox.Enabled' : 'Checkbox.Disabled');
});
}
}
@ -56,7 +61,7 @@ export default class Row { @@ -56,7 +61,7 @@ export default class Row {
const i = options.radioField || options.checkboxField;
i.label.classList.add('disable-hover');
} else {
if(options.title) {
if(options.title || options.titleLangKey) {
let c: HTMLElement;
if(options.titleRight) {
c = document.createElement('div');
@ -68,7 +73,11 @@ export default class Row { @@ -68,7 +73,11 @@ export default class Row {
this.title = document.createElement('div');
this.title.classList.add('row-title');
this.title.innerHTML = options.title;
if(options.title) {
this.title.innerHTML = options.title;
} else {
_i18n(this.title, options.titleLangKey);
}
c.append(this.title);
if(options.titleRight) {
@ -118,4 +127,4 @@ export default class Row { @@ -118,4 +127,4 @@ export default class Row {
export const RadioFormFromRows = (rows: Row[], onChange: (value: string) => void) => {
return RadioForm(rows.map(r => ({container: r.container, input: r.radioField.input})), onChange);
};
};

7
src/components/sidebarLeft/index.ts

@ -24,7 +24,6 @@ import AppContactsTab from "./tabs/contacts"; @@ -24,7 +24,6 @@ import AppContactsTab from "./tabs/contacts";
import AppArchivedTab from "./tabs/archivedTab";
import AppAddMembersTab from "./tabs/addMembers";
import { i18n_, LangPackKey } from "../../lib/langPack";
import ButtonMenuToggle from "../buttonMenuToggle";
import ButtonMenu, { ButtonMenuItemOptions } from "../buttonMenu";
export const LEFT_COLUMN_ACTIVE_CLASSNAME = 'is-left-column-shown';
@ -84,7 +83,7 @@ export class AppSidebarLeft extends SidebarSlider { @@ -84,7 +83,7 @@ export class AppSidebarLeft extends SidebarSlider {
const btnArchive: ButtonMenuItemOptions = {
icon: 'archive',
text: 'Archived',
text: 'ChatList.Menu.Archived',
onClick: () => {
new AppArchivedTab(this).open();
}
@ -92,7 +91,7 @@ export class AppSidebarLeft extends SidebarSlider { @@ -92,7 +91,7 @@ export class AppSidebarLeft extends SidebarSlider {
const btnMenu = ButtonMenu([{
icon: 'newgroup',
text: 'New Group',
text: 'NewGroup',
onClick: onNewGroupClick
}, {
icon: 'user',
@ -114,7 +113,7 @@ export class AppSidebarLeft extends SidebarSlider { @@ -114,7 +113,7 @@ export class AppSidebarLeft extends SidebarSlider {
}
}, {
icon: 'help btn-disabled',
text: 'Help',
text: 'SettingsHelp',
onClick: () => {
}

8
src/components/sidebarLeft/tabs/background.ts

@ -20,16 +20,16 @@ import { wrapPhoto } from "../../wrappers"; @@ -20,16 +20,16 @@ import { wrapPhoto } from "../../wrappers";
export default class AppBackgroundTab extends SliderSuperTab {
init() {
this.container.classList.add('background-container');
this.title.innerText = 'Chat Background';
this.setTitle('ChatBackground');
{
const container = generateSection(this.scrollable);
const uploadButton = Button('btn-primary btn-transparent', {icon: 'cameraadd', text: 'Upload Wallpaper', disabled: true});
const colorButton = Button('btn-primary btn-transparent', {icon: 'colorize', text: 'Set a Color', disabled: true});
const uploadButton = Button('btn-primary btn-transparent', {icon: 'cameraadd', text: 'ChatBackground.UploadWallpaper', disabled: true});
const colorButton = Button('btn-primary btn-transparent', {icon: 'colorize', text: 'ChatBackground.SetColor', disabled: true});
const blurCheckboxField = new CheckboxField({
text: 'Blur Wallpaper Image',
text: 'ChatBackground.Blur',
name: 'blur',
stateKey: 'settings.background.blur',
withRipple: true

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

@ -2,7 +2,6 @@ import { SliderSuperTab } from "../../slider"; @@ -2,7 +2,6 @@ import { SliderSuperTab } from "../../slider";
import lottieLoader, { RLottiePlayer } from "../../../lib/lottieLoader";
import { RichTextProcessor } from "../../../lib/richtextprocessor";
import { attachClickEvent, cancelEvent, positionElementByIndex } from "../../../helpers/dom";
import { ripple } from "../../ripple";
import { toast } from "../../toast";
import type { MyDialogFilter } from "../../../lib/storages/filters";
import type { DialogFilterSuggested, DialogFilter } from "../../../layer";
@ -16,7 +15,7 @@ import rootScope from "../../../lib/rootScope"; @@ -16,7 +15,7 @@ import rootScope from "../../../lib/rootScope";
import AppEditFolderTab from "./editFolder";
import Row from "../../row";
import { SettingSection } from "..";
import { i18n_ } from "../../../lib/langPack";
import { i18n, i18n_, LangPackKey } from "../../../lib/langPack";
export default class AppChatFoldersTab extends SliderSuperTab {
private createFolderBtn: HTMLElement;
@ -30,13 +29,12 @@ export default class AppChatFoldersTab extends SliderSuperTab { @@ -30,13 +29,12 @@ export default class AppChatFoldersTab extends SliderSuperTab {
private renderFolder(dialogFilter: DialogFilterSuggested | DialogFilter | MyDialogFilter, container?: HTMLElement, div?: HTMLElement) {
let filter: DialogFilter | MyDialogFilter;
let description = '';
let d: string[] = [];
let d: HTMLElement[] = [];
if(dialogFilter._ === 'dialogFilterSuggested') {
filter = dialogFilter.filter;
description = dialogFilter.description;
} else {
filter = dialogFilter;
description = '';
let enabledFilters = Object.keys(filter.pFlags).length;
/* (['include_peers', 'exclude_peers'] as ['include_peers', 'exclude_peers']).forEach(key => {
@ -44,18 +42,17 @@ export default class AppChatFoldersTab extends SliderSuperTab { @@ -44,18 +42,17 @@ export default class AppChatFoldersTab extends SliderSuperTab {
}); */
if(enabledFilters === 1) {
description = 'All ';
const pFlags = filter.pFlags;
if(pFlags.contacts) description += 'Contacts';
else if(pFlags.non_contacts) description += 'Non-Contacts';
else if(pFlags.groups) description += 'Groups';
else if(pFlags.broadcasts) description += 'Channels';
else if(pFlags.bots) description += 'Bots';
else if(pFlags.exclude_muted) description += 'Unmuted';
else if(pFlags.exclude_read) description += 'Unread';
else if(pFlags.exclude_archived) description += 'Unarchived';
d.push(description);
let k: LangPackKey;
if(pFlags.contacts) k = 'FilterAllContacts';
else if(pFlags.non_contacts) k = 'FilterAllNonContacts';
else if(pFlags.groups) k = 'FilterAllGroups';
else if(pFlags.broadcasts) k = 'FilterAllChannels';
else if(pFlags.bots) k = 'FilterAllBots';
else if(pFlags.exclude_muted) k = 'FilterAllUnmuted';
else if(pFlags.exclude_read) k = 'FilterAllUnread';
else if(pFlags.exclude_archived) k = 'FilterAllUnarchived';
d.push(i18n(k));
} else {
const folder = appMessagesManager.dialogsStorage.getFolder(filter.id);
let chats = 0, channels = 0, groups = 0;
@ -65,18 +62,32 @@ export default class AppChatFoldersTab extends SliderSuperTab { @@ -65,18 +62,32 @@ export default class AppChatFoldersTab extends SliderSuperTab {
else chats++;
}
if(chats) d.push(chats + ' chats');
if(channels) d.push(channels + ' channels');
if(groups) d.push(groups + ' groups');
if(chats) d.push(i18n('Chats', [chats]));
if(channels) d.push(i18n('Channels', [channels]));
if(groups) d.push(i18n('Groups', [groups]));
}
}
if(!div) {
const row = new Row({
title: RichTextProcessor.wrapEmojiText(filter.title),
subtitle: d.length ? d.join(', ') : description,
subtitle: description,
clickable: true
});
if(d.length) {
let arr: HTMLElement[] = d.slice(0, 1);
for(let i = 1; i < d.length; ++i) {
const isLast = (d.length - 1) === i;
const delimiterKey: LangPackKey = isLast ? 'WordDelimiterLast' : 'WordDelimiter';
arr.push(i18n(delimiterKey));
arr.push(d[i]);
}
arr.forEach(el => {
row.subtitle.append(el);
});
}
div = row.container;
@ -119,12 +130,12 @@ export default class AppChatFoldersTab extends SliderSuperTab { @@ -119,12 +130,12 @@ export default class AppChatFoldersTab extends SliderSuperTab {
});
this.foldersSection = new SettingSection({
name: 'ChatList.Filter.List.Header'
name: 'Filters'
});
this.foldersSection.container.style.display = 'none';
this.suggestedSection = new SettingSection({
name: 'ChatList.Filter.Recommended.Header'
name: 'FilterRecommended'
});
this.suggestedSection.container.style.display = 'none';
@ -208,7 +219,7 @@ export default class AppChatFoldersTab extends SliderSuperTab { @@ -208,7 +219,7 @@ export default class AppChatFoldersTab extends SliderSuperTab {
suggestedFilters.forEach(filter => {
const div = this.renderFolder(filter);
const button = Button('btn-primary btn-color-primary', {text: 'ChatList.Filter.Recommended.Add'});
const button = Button('btn-primary btn-color-primary', {text: 'Add'});
div.append(button);
this.suggestedSection.content.append(div);

19
src/components/sidebarLeft/tabs/editFolder.ts

@ -39,15 +39,14 @@ export default class AppEditFolderTab extends SliderSuperTab { @@ -39,15 +39,14 @@ export default class AppEditFolderTab extends SliderSuperTab {
this.container.classList.add('edit-folder-container');
this.caption = document.createElement('div');
this.caption.classList.add('caption');
this.caption.append(i18n(`Choose chats and types of chats that will
appear and never appear in this folder.`));
this.caption.append(i18n('FilterIncludeExcludeInfo'));
this.stickerContainer = document.createElement('div');
this.stickerContainer.classList.add('sticker-container');
this.confirmBtn = ButtonIcon('check btn-confirm hide blue');
const deleteFolderButton: ButtonMenuItemOptions = {
icon: 'delete danger',
text: 'Delete Folder',
text: 'FilterMenuDelete',
onClick: () => {
deleteFolderButton.element.setAttribute('disabled', 'true');
appMessagesManager.filtersStorage.updateDialogFilter(this.filter, true).then(bool => {
@ -68,13 +67,13 @@ appear and never appear in this folder.`)); @@ -68,13 +67,13 @@ appear and never appear in this folder.`));
inputWrapper.classList.add('input-wrapper');
this.nameInputField = new InputField({
label: 'Folder Name',
label: 'FilterNameInputLabel',
maxLength: MAX_FOLDER_NAME_LENGTH
});
inputWrapper.append(this.nameInputField.container);
const generateList = (className: string, h2Text: LangPackKey, buttons: {icon: string, name?: string, withRipple?: true, text: string}[], to: any) => {
const generateList = (className: string, h2Text: LangPackKey, buttons: {icon: string, name?: string, withRipple?: true, text: LangPackKey}[], to: any) => {
const container = document.createElement('div');
container.classList.add('folder-list', className);
@ -104,7 +103,7 @@ appear and never appear in this folder.`)); @@ -104,7 +103,7 @@ appear and never appear in this folder.`));
return container;
};
this.include_peers = generateList('folder-list-included', 'ChatList.Filter.Include.Header', [{
this.include_peers = generateList('folder-list-included', 'FilterInclude', [{
icon: 'add primary',
text: 'ChatList.Filter.Include.AddChat',
withRipple: true
@ -130,7 +129,7 @@ appear and never appear in this folder.`)); @@ -130,7 +129,7 @@ appear and never appear in this folder.`));
name: 'bots'
}], this.flags);
this.exclude_peers = generateList('folder-list-excluded', 'ChatList.Filter.Exclude.Header', [{
this.exclude_peers = generateList('folder-list-excluded', 'FilterExclude', [{
icon: 'minus primary',
text: 'ChatList.Filter.Exclude.AddChat',
withRipple: true
@ -227,7 +226,7 @@ appear and never appear in this folder.`)); @@ -227,7 +226,7 @@ appear and never appear in this folder.`));
private onCreateOpen() {
this.caption.style.display = '';
this.setTitle('New Folder');
this.setTitle('FilterNew');
this.menuBtn.classList.add('hide');
this.confirmBtn.classList.remove('hide');
this.nameInputField.value = '';
@ -240,7 +239,7 @@ appear and never appear in this folder.`)); @@ -240,7 +239,7 @@ appear and never appear in this folder.`));
private onEditOpen() {
this.caption.style.display = 'none';
this.setTitle(this.type === 'create' ? 'New Folder' : 'Edit Folder');
this.setTitle(this.type === 'create' ? 'FilterNew' : 'FilterHeaderEdit');
if(this.type === 'edit') {
this.menuBtn.classList.remove('hide');
@ -344,4 +343,4 @@ appear and never appear in this folder.`)); @@ -344,4 +343,4 @@ appear and never appear in this folder.`));
return ret;
}
}
}

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

@ -31,7 +31,7 @@ export default class AppEditProfileTab extends SliderSuperTab { @@ -31,7 +31,7 @@ export default class AppEditProfileTab extends SliderSuperTab {
inputWrapper.classList.add('input-wrapper');
this.firstNameInputField = new InputField({
label: 'Login.Register.FirstName.Placeholder',
label: 'EditProfile.FirstNameLabel',
name: 'first-name',
maxLength: 70
});
@ -41,7 +41,7 @@ export default class AppEditProfileTab extends SliderSuperTab { @@ -41,7 +41,7 @@ export default class AppEditProfileTab extends SliderSuperTab {
maxLength: 64
});
this.bioInputField = new InputField({
label: 'AccountSettings.Bio',
label: 'EditProfile.BioLabel',
name: 'bio',
maxLength: 70
});
@ -76,7 +76,7 @@ export default class AppEditProfileTab extends SliderSuperTab { @@ -76,7 +76,7 @@ export default class AppEditProfileTab extends SliderSuperTab {
this.usernameInputField = new UsernameInputField({
peerId: 0,
label: 'EditAccount.Username',
label: 'EditProfile.Username.Label',
name: 'username',
plainText: true,
listenerSetter: this.listenerSetter,
@ -84,21 +84,21 @@ export default class AppEditProfileTab extends SliderSuperTab { @@ -84,21 +84,21 @@ export default class AppEditProfileTab extends SliderSuperTab {
this.editPeer.handleChange();
this.setProfileUrl();
},
availableText: 'Username is available',
takenText: 'Username is already taken',
invalidText: 'Username is invalid'
availableText: 'EditProfile.Username.Available',
takenText: 'EditProfile.Username.Taken',
invalidText: 'EditProfile.Username.Invalid'
});
inputWrapper.append(this.usernameInputField.container);
const caption = document.createElement('div');
caption.classList.add('caption');
caption.append(i18n('UsernameSettings.ChangeDescription'));
caption.append(i18n('EditProfile.Username.Help'));
caption.append(document.createElement('br'), document.createElement('br'));
const profileUrlContainer = this.profileUrlContainer = document.createElement('div');
profileUrlContainer.classList.add('profile-url-container');
profileUrlContainer.append(i18n('This link opens a chat with you:'));
profileUrlContainer.append(i18n('UsernameHelpLink', ['']));
const profileUrlAnchor = this.profileUrlAnchor = document.createElement('a');
profileUrlAnchor.classList.add('profile-url');

47
src/components/sidebarLeft/tabs/generalSettings.ts

@ -10,6 +10,7 @@ import { isApple } from "../../../helpers/userAgent"; @@ -10,6 +10,7 @@ import { isApple } from "../../../helpers/userAgent";
import Row from "../../row";
import { attachClickEvent } from "../../../helpers/dom";
import AppBackgroundTab from "./background";
import { LangPackKey, _i18n } from "../../../lib/langPack";
export class RangeSettingSelector {
public container: HTMLDivElement;
@ -17,7 +18,7 @@ export class RangeSettingSelector { @@ -17,7 +18,7 @@ export class RangeSettingSelector {
public onChange: (value: number) => void;
constructor(name: string, step: number, initialValue: number, minValue: number, maxValue: number) {
constructor(name: LangPackKey, step: number, initialValue: number, minValue: number, maxValue: number) {
const BASE_CLASS = 'range-setting-selector';
this.container = document.createElement('div');
this.container.classList.add(BASE_CLASS);
@ -27,7 +28,7 @@ export class RangeSettingSelector { @@ -27,7 +28,7 @@ export class RangeSettingSelector {
const nameDiv = document.createElement('div');
nameDiv.classList.add(BASE_CLASS + '-name');
nameDiv.innerHTML = name;
_i18n(nameDiv, name);
const valueDiv = document.createElement('div');
valueDiv.classList.add(BASE_CLASS + '-value');
@ -55,26 +56,26 @@ export class RangeSettingSelector { @@ -55,26 +56,26 @@ export class RangeSettingSelector {
export default class AppGeneralSettingsTab extends SliderSuperTab {
init() {
this.container.classList.add('general-settings-container');
this.title.innerText = 'General';
this.setTitle('General');
const section = generateSection.bind(null, this.scrollable);
{
const container = section('Settings');
const range = new RangeSettingSelector('Message Text Size', 1, rootScope.settings.messagesTextSize, 12, 20);
const range = new RangeSettingSelector('TextSize', 1, rootScope.settings.messagesTextSize, 12, 20);
range.onChange = (value) => {
appStateManager.setByKey('settings.messagesTextSize', value);
};
const chatBackgroundButton = Button('btn-primary btn-transparent', {icon: 'photo', text: 'Chat Background'});
const chatBackgroundButton = Button('btn-primary btn-transparent', {icon: 'photo', text: 'ChatBackground'});
attachClickEvent(chatBackgroundButton, () => {
new AppBackgroundTab(this.slider).open();
});
const animationsCheckboxField = new CheckboxField({
text: 'Enable Animations',
text: 'EnableAnimations',
name: 'animations',
stateKey: 'settings.animationsEnabled',
withRipple: true
@ -84,58 +85,58 @@ export default class AppGeneralSettingsTab extends SliderSuperTab { @@ -84,58 +85,58 @@ export default class AppGeneralSettingsTab extends SliderSuperTab {
}
{
const container = section('Keyboard');
const container = section('General.Keyboard');
const form = document.createElement('form');
const enterRow = new Row({
radioField: new RadioField({
text: 'Send by Enter',
text: 'General.SendShortcut.Enter',
name: 'send-shortcut',
value: 'enter',
stateKey: 'settings.sendShortcut'
}),
subtitle: 'New line by Shift + Enter',
subtitleLangKey: 'General.SendShortcut.NewLine.ShiftEnter'
});
const ctrlEnterRow = new Row({
radioField: new RadioField({
text: `Send by ${isApple ? '⌘' : 'Ctrl'} + Enter`,
name: 'send-shortcut',
value: 'ctrlEnter',
stateKey: 'settings.sendShortcut'
}),
subtitle: 'New line by Enter',
subtitleLangKey: 'General.SendShortcut.NewLine.Enter'
});
_i18n(ctrlEnterRow.radioField.main, 'General.SendShortcut.CtrlEnter', [isApple ? '⌘' : 'Ctrl']);
form.append(enterRow.container, ctrlEnterRow.container);
container.append(form);
}
{
const container = section('Auto-Download Media');
const container = section('AutoDownloadMedia');
//container.classList.add('sidebar-left-section-disabled');
const contactsCheckboxField = new CheckboxField({
text: 'Contacts',
text: 'AutodownloadContacts',
name: 'contacts',
stateKey: 'settings.autoDownload.contacts',
withRipple: true
});
const privateCheckboxField = new CheckboxField({
text: 'Private Chats',
text: 'AutodownloadPrivateChats',
name: 'private',
stateKey: 'settings.autoDownload.private',
withRipple: true
});
const groupsCheckboxField = new CheckboxField({
text: 'Group Chats',
text: 'AutodownloadGroupChats',
name: 'groups',
stateKey: 'settings.autoDownload.groups',
withRipple: true
});
const channelsCheckboxField = new CheckboxField({
text: 'Channels',
text: 'AutodownloadChannels',
name: 'channels',
stateKey: 'settings.autoDownload.channels',
withRipple: true
@ -145,17 +146,17 @@ export default class AppGeneralSettingsTab extends SliderSuperTab { @@ -145,17 +146,17 @@ export default class AppGeneralSettingsTab extends SliderSuperTab {
}
{
const container = section('Auto-Play Media');
const container = section('General.AutoplayMedia');
//container.classList.add('sidebar-left-section-disabled');
const gifsCheckboxField = new CheckboxField({
text: 'GIFs',
text: 'AutoplayGIF',
name: 'gifs',
stateKey: 'settings.autoPlay.gifs',
withRipple: true
});
const videosCheckboxField = new CheckboxField({
text: 'Videos',
text: 'AutoplayVideo',
name: 'videos',
stateKey: 'settings.autoPlay.videos',
withRipple: true
@ -165,16 +166,16 @@ export default class AppGeneralSettingsTab extends SliderSuperTab { @@ -165,16 +166,16 @@ export default class AppGeneralSettingsTab extends SliderSuperTab {
}
{
const container = section('Stickers');
const container = section('Telegram.InstalledStickerPacksController');
const suggestCheckboxField = new CheckboxField({
text: 'Suggest Stickers by Emoji',
text: 'Stickers.SuggestStickers',
name: 'suggest',
stateKey: 'settings.stickers.suggest',
withRipple: true
});
const loopCheckboxField = new CheckboxField({
text: 'Loop Animated Stickers',
text: 'InstalledStickers.LoopAnimated',
name: 'loop',
stateKey: 'settings.stickers.loop',
withRipple: true
@ -190,4 +191,4 @@ export default class AppGeneralSettingsTab extends SliderSuperTab { @@ -190,4 +191,4 @@ export default class AppGeneralSettingsTab extends SliderSuperTab {
this.init = null;
}
}
}
}

12
src/components/sidebarLeft/tabs/includedChats.ts

@ -124,7 +124,7 @@ export default class AppIncludedChatsTab extends SliderSuperTab { @@ -124,7 +124,7 @@ export default class AppIncludedChatsTab extends SliderSuperTab {
dom.containerEl.append(this.checkbox(selected));
if(selected) dom.listEl.classList.add('active');
let subtitle: LangPackKey;
/* let subtitle: LangPackKey;
if(peerId > 0) {
if(peerId === rootScope.myId) {
@ -138,7 +138,7 @@ export default class AppIncludedChatsTab extends SliderSuperTab { @@ -138,7 +138,7 @@ export default class AppIncludedChatsTab extends SliderSuperTab {
subtitle = appPeersManager.isBroadcast(peerId) ? 'Channel' : 'Group';
}
_i18n(dom.lastMessageSpan, subtitle);
_i18n(dom.lastMessageSpan, subtitle); */
});
};
@ -149,19 +149,19 @@ export default class AppIncludedChatsTab extends SliderSuperTab { @@ -149,19 +149,19 @@ export default class AppIncludedChatsTab extends SliderSuperTab {
}
this.confirmBtn.style.display = this.type === 'excluded' ? '' : 'none';
this.setTitle(this.type === 'included' ? 'Included Chats' : 'Excluded Chats');
this.setTitle(this.type === 'included' ? 'FilterAlwaysShow' : 'FilterNeverShow');
const filter = this.filter;
const fragment = document.createDocumentFragment();
const dd = document.createElement('div');
dd.classList.add('sidebar-left-h2');
_i18n(dd, 'ChatList.Add.TopSeparator');
_i18n(dd, 'FilterChatTypes');
const categories = document.createElement('div');
categories.classList.add('folder-categories');
let details: {[flag: string]: {ico: string, text: string}};
let details: {[flag: string]: {ico: string, text: LangPackKey}};
if(this.type === 'excluded') {
details = {
exclude_muted: {ico: 'mute', text: 'ChatList.Filter.MutedChats'},
@ -192,7 +192,7 @@ export default class AppIncludedChatsTab extends SliderSuperTab { @@ -192,7 +192,7 @@ export default class AppIncludedChatsTab extends SliderSuperTab {
const d = document.createElement('div');
d.classList.add('sidebar-left-h2');
_i18n(d, 'ChatList.Add.BottomSeparator');
_i18n(d, 'FilterChats');
fragment.append(dd, categories, hr, d);

26
src/components/sidebarLeft/tabs/notifications.ts

@ -18,7 +18,7 @@ export default class AppNotificationsTab extends SliderSuperTabEventable { @@ -18,7 +18,7 @@ export default class AppNotificationsTab extends SliderSuperTabEventable {
const NotifySection = (options: {
name: LangPackKey,
typeText: string,
typeText: LangPackKey,
inputKey: InputNotifyKey,
}) => {
const section = new SettingSection({
@ -27,12 +27,12 @@ export default class AppNotificationsTab extends SliderSuperTabEventable { @@ -27,12 +27,12 @@ export default class AppNotificationsTab extends SliderSuperTabEventable {
const enabledRow = new Row({
checkboxField: new CheckboxField({text: options.typeText, checked: true}),
subtitle: 'Loading...',
subtitleLangKey: 'Loading',
});
const previewEnabledRow = new Row({
checkboxField: new CheckboxField({text: 'Message preview', checked: true}),
subtitle: 'Loading...',
checkboxField: new CheckboxField({text: 'Notifications.MessagePreview', checked: true}),
subtitleLangKey: 'Loading',
});
section.content.append(enabledRow.container, previewEnabledRow.container);
@ -80,35 +80,35 @@ export default class AppNotificationsTab extends SliderSuperTabEventable { @@ -80,35 +80,35 @@ export default class AppNotificationsTab extends SliderSuperTabEventable {
NotifySection({
name: 'AutoDownloadSettings.TypePrivateChats',
typeText: 'Notifications for private chats',
typeText: 'NotificationsForPrivateChats',
inputKey: 'inputNotifyUsers'
});
NotifySection({
name: 'DataAndStorage.CategorySettings.GroupChats',
typeText: 'Notifications for groups',
name: 'AutoDownloadSettings.TypeGroupChats',
typeText: 'NotificationsForGroups',
inputKey: 'inputNotifyChats'
});
NotifySection({
name: 'AutoDownloadSettings.TypeChannels',
typeText: 'Notifications for channels',
typeText: 'NotificationsForChannels',
inputKey: 'inputNotifyBroadcasts'
});
{
const section = new SettingSection({
name: 'Suggest.Localization.Other'
name: 'NotificationsOther'
});
const contactsSignUpRow = new Row({
checkboxField: new CheckboxField({text: 'Contacts joined Telegram', checked: true}),
subtitle: 'Loading...',
checkboxField: new CheckboxField({text: 'ContactJoined', checked: true}),
subtitleLangKey: 'Loading',
});
const soundRow = new Row({
checkboxField: new CheckboxField({text: 'Notification sound', checked: true, stateKey: 'settings.notifications.sound'}),
subtitle: 'Enabled',
checkboxField: new CheckboxField({text: 'Notifications.Sound', checked: true, stateKey: 'settings.notifications.sound'}),
subtitleLangKey: 'Checkbox.Enabled',
});
section.content.append(contactsSignUpRow.container, soundRow.container);

52
src/components/sidebarLeft/tabs/privacyAndSecurity.ts

@ -19,6 +19,7 @@ import AppBlockedUsersTab from "./blockedUsers"; @@ -19,6 +19,7 @@ import AppBlockedUsersTab from "./blockedUsers";
import appUsersManager from "../../../lib/appManagers/appUsersManager";
import rootScope from "../../../lib/rootScope";
import { convertKeyToInputKey } from "../../../helpers/string";
import { LangPackKey, _i18n } from "../../../lib/langPack";
export default class AppPrivacyAndSecurityTab extends SliderSuperTab {
private activeSessionsRow: Row;
@ -26,11 +27,11 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTab { @@ -26,11 +27,11 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTab {
protected init() {
this.container.classList.add('privacy-container');
this.title.innerText = 'Privacy and Security';
this.setTitle('PrivacySettings');
const section = generateSection.bind(null, this.scrollable);
const SUBTITLE = 'Loading...';
const SUBTITLE: LangPackKey = 'Loading';
{
const section = new SettingSection({noDelimiter: true});
@ -38,8 +39,8 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTab { @@ -38,8 +39,8 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTab {
let blockedPeerIds: number[];
const blockedUsersRow = new Row({
icon: 'deleteuser',
title: 'Blocked Users',
subtitle: SUBTITLE,
titleLangKey: 'BlockedUsers',
subtitleLangKey: SUBTITLE,
clickable: () => {
const tab = new AppBlockedUsersTab(this.slider);
tab.peerIds = blockedPeerIds;
@ -51,8 +52,8 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTab { @@ -51,8 +52,8 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTab {
let passwordState: AccountPassword;
const twoFactorRowOptions = {
icon: 'lock',
title: 'Two-Step Verification',
subtitle: SUBTITLE,
titleLangKey: 'TwoStepVerification' as LangPackKey,
subtitleLangKey: SUBTITLE,
clickable: (e: Event) => {
let tab: AppTwoStepVerificationTab | AppTwoStepVerificationEnterPasswordTab | AppTwoStepVerificationEmailConfirmationTab;
if(passwordState.pFlags.has_password) {
@ -77,8 +78,8 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTab { @@ -77,8 +78,8 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTab {
const activeSessionsRow = this.activeSessionsRow = new Row({
icon: 'activesessions',
title: 'Active Sessions',
subtitle: SUBTITLE,
titleLangKey: 'SessionsTitle',
subtitleLangKey: SUBTITLE,
clickable: () => {
const tab = new AppActiveSessionsTab(this.slider);
tab.privacyTab = this;
@ -94,7 +95,12 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTab { @@ -94,7 +95,12 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTab {
let blockedCount: number;
const setBlockedCount = (count: number) => {
blockedCount = count;
blockedUsersRow.subtitle.innerText = count ? (count + ' ' + (count > 1 ? 'users' : 'user')) : 'None';
if(count) {
_i18n(blockedUsersRow.subtitle, 'Privacy.BlockedUsers', [count]);
} else {
_i18n(blockedUsersRow.subtitle, 'Privacy.BlockedUsers.None');
}
};
this.listenerSetter.add(rootScope, 'peer_block', () => {
@ -128,7 +134,7 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTab { @@ -128,7 +134,7 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTab {
}
{
const container = section('Privacy');
const container = section('PrivacyTitle');
container.classList.add('privacy-navigation-container');
@ -137,48 +143,48 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTab { @@ -137,48 +143,48 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTab {
}> = {};
const numberVisibilityRow = rowsByKeys['inputPrivacyKeyPhoneNumber'] = new Row({
title: 'Who can see my phone number?',
subtitle: SUBTITLE,
titleLangKey: 'PrivacyPhoneTitle',
subtitleLangKey: SUBTITLE,
clickable: () => {
new AppPrivacyPhoneNumberTab(this.slider).open()
}
});
const lastSeenTimeRow = rowsByKeys['inputPrivacyKeyStatusTimestamp'] = new Row({
title: 'Who can see your Last Seen time?',
subtitle: SUBTITLE,
titleLangKey: 'LastSeenTitle',
subtitleLangKey: SUBTITLE,
clickable: () => {
new AppPrivacyLastSeenTab(this.slider).open()
}
});
const photoVisibilityRow = rowsByKeys['inputPrivacyKeyProfilePhoto'] = new Row({
title: 'Who can see my profile photo?',
subtitle: SUBTITLE,
titleLangKey: 'PrivacyProfilePhotoTitle',
subtitleLangKey: SUBTITLE,
clickable: () => {
new AppPrivacyProfilePhotoTab(this.slider).open();
}
});
const callRow = rowsByKeys['inputPrivacyKeyPhoneCall'] = new Row({
title: 'Who can call me?',
subtitle: SUBTITLE,
titleLangKey: 'WhoCanCallMe',
subtitleLangKey: SUBTITLE,
clickable: () => {
new AppPrivacyCallsTab(this.slider).open();
}
});
const linkAccountRow = rowsByKeys['inputPrivacyKeyForwards'] = new Row({
title: 'Who can add a link to my account when forwarding my messages?',
subtitle: SUBTITLE,
titleLangKey: 'PrivacyForwardsTitle',
subtitleLangKey: SUBTITLE,
clickable: () => {
new AppPrivacyForwardMessagesTab(this.slider).open();
}
});
const groupChatsAddRow = rowsByKeys['inputPrivacyKeyChatInvite'] = new Row({
title: 'Who can add me to group chats?',
subtitle: SUBTITLE,
titleLangKey: 'WhoCanAddMe',
subtitleLangKey: SUBTITLE,
clickable: () => {
new AppPrivacyAddToGroupsTab(this.slider).open();
}
@ -216,7 +222,7 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTab { @@ -216,7 +222,7 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTab {
apiManager.invokeApi('account.getAuthorizations').then(auths => {
this.activeSessionsRow.freezed = false;
this.authorizations = auths.authorizations;
this.activeSessionsRow.subtitle.innerText = this.authorizations.length + ' ' + (this.authorizations.length !== 1 ? 'devices' : 'device');
_i18n(this.activeSessionsRow.subtitle, 'Privacy.Devices', [this.authorizations.length]);
//console.log('auths', auths);
});
}

140
src/lang.ts

@ -0,0 +1,140 @@ @@ -0,0 +1,140 @@
const lang = {
FilterIncludeExcludeInfo: 'Choose chats and types of chats that will\nappear and never appear in this folder.',
FilterNameInputLabel: 'Folder Name',
FilterMenuDelete: 'Delete Folder',
FilterHeaderEdit: 'Edit Folder',
FilterAllGroups: 'All Groups',
FilterAllContacts: 'All Contacts',
FilterAllNonContacts: 'All Non-Contacts',
FilterAllChannels: 'All Channels',
FilterAllBots: 'All Bots',
FilterAllUnmuted: 'All Unmuted',
FilterAllUnread: 'All Unread',
FilterAllUnarchived: 'All Unarchived',
WordDelimiter: ', ',
WordDelimiterLast: ' and ',
"EditProfile.FirstNameLabel": 'Name',
"EditProfile.BioLabel": 'Bio (optional)',
"EditProfile.Username.Label": 'Username (optional)',
"EditProfile.Username.Available": 'Username is available',
"EditProfile.Username.Taken": 'Username is already taken',
"EditProfile.Username.Invalid": 'Username is invalid',
"EditProfile.Username.Help": "You can choose a username on Telegram. If you do, people will be able to find you by this username and contact you without needing your phone number.\n\nYou can use a–z, 0–9 and underscores. Minimum length is 5 characters.",
"ChatList.Menu.Archived": "Archived",
Saved: "Saved",
"General.Keyboard": "Keyboard",
"General.SendShortcut.Enter": "Send by Enter",
"General.SendShortcut.CtrlEnter": "Send by %s + Enter",
"General.SendShortcut.NewLine.ShiftEnter": "New line by Shift + Enter",
"General.SendShortcut.NewLine.Enter": "New line by Enter",
"General.AutoplayMedia": "Auto-Play Media",
"ChatBackground.UploadWallpaper": "Upload Wallpaper",
"ChatBackground.SetColor": "Upload Wallpaper",
"ChatBackground.Blur": "Upload Wallpaper",
"Notifications.Sound": "Notification Sound",
"Notifications.MessagePreview": "Message preview",
"Checkbox.Enabled": "Enabled",
"Checkbox.Disabled": "Disabled",
"Privacy.Devices": {
one_value: '%1$d device',
other_value: '%1$d devices'
},
"Privacy.BlockedUsers": {
one_value: '%1$d user',
other_value: '%1$d users',
},
"Privacy.BlockedUsers.None": 'None',
// * android
FilterAlwaysShow: 'Include Chats',
FilterNeverShow: 'Exclude Chats',
FilterInclude: 'Included Chats',
FilterExclude: 'Excluded Chats',
FilterChatTypes: 'Chat types',
FilterChats: 'Chats',
FilterNew: 'New Folder',
Filters: 'Folders',
FilterRecommended: 'Recommended Folders',
Add: 'Add',
Chats: {
one_value: '%1$d chat',
other_value: '%1$d chats'
},
Channels: {
one_value: '%1$d channel',
other_value: '%1$d channels'
},
Groups: {
one_value: '%1$d group',
other_value: '%1$d groups'
},
UsernameHelpLink: "This link opens a chat with you:\n%1$s",
NewGroup: "New Group",
Contacts: "Contacts",
SavedMessages: "Saved Messages",
Settings: "Settings",
SettingsHelp: "Help",
General: "General",
TextSize: "Message Text Size",
ChatBackground: "Chat Background",
EnableAnimations: "Enable Animations",
AutoDownloadMedia: "Auto-Download Media",
AutodownloadContacts: 'Contacts',
AutodownloadPrivateChats: 'Private Chats',
AutodownloadGroupChats: 'Group Chats',
AutodownloadChannels: 'Channels',
AutoplayGIF: 'GIFs',
AutoplayVideo: 'Videos',
NotificationsForGroups: 'Notifications for groups',
NotificationsForPrivateChats: 'Notifications for private chats',
NotificationsForChannels: 'Notifications for channels',
NotificationsOther: 'Other',
ContactJoined: 'Contact joined Telegram',
Loading: "Loading...",
BlockedUsers: "Blocked Users",
TwoStepVerification: "Two-Step Verification",
PrivacySettings: "Privacy and Security",
PrivacyTitle: "Privacy",
PrivacyPhoneTitle: "Who can see my phone number?",
PrivacyProfilePhotoTitle: "Who can see my profile photos & videos?",
PrivacyForwardsTitle: "Who can add a link to my account when forwarding my messages?",
LastSeenTitle: "Who can see your Last Seen time?",
SessionsTitle: "Active Sessions",
WhoCanCallMe: "Who can call me?",
WhoCanAddMe: "Who can add me to group chats?",
// * macos
"ChatList.Filter.Header": "Create folders for different groups of chats and quickly switch between them.",
"ChatList.Filter.NewTitle": "Create Folder",
"ChatList.Filter.List.Title": "Chat Folders",
"ChatList.Filter.Include.AddChat": "Add Chats",
"ChatList.Filter.Exclude.AddChat": "Add Chats",
"ChatList.Filter.All": "All",
"ChatList.Filter.Contacts": "Contacts",
"ChatList.Filter.NonContacts": "Non-Contacts",
"ChatList.Filter.Groups": "Groups",
"ChatList.Filter.Channels": "Channels",
"ChatList.Filter.Bots": "Bots",
"ChatList.Filter.MutedChats": "Muted",
"ChatList.Filter.ReadChats": "Read",
"ChatList.Filter.Archive": "Archived",
"Bio.Description": "Any details such as age, occupation or city.\nExample: 23 y.o. designer from San Francisco",
"EditAccount.Username": "Username",
"EditAccount.Title": "Edit Profile",
"EditAccount.Logout": "Log Out",
"Login.Register.LastName.Placeholder": "Last Name",
"AccountSettings.Filters": "Chat Folders",
"AccountSettings.Notifications": "Notifications and Sounds",
"AccountSettings.PrivacyAndSecurity": "Privacy and Security",
"AccountSettings.Language": "Language",
"Telegram.GeneralSettingsViewController": "General Settings",
"Telegram.InstalledStickerPacksController": "Stickers",
"Telegram.NotificationSettingsViewController": "Notifications",
"Stickers.SuggestStickers": "Suggest Stickers by Emoji",
"InstalledStickers.LoopAnimated": "Loop Animated Stickers",
"AutoDownloadSettings.TypePrivateChats": "Private Chats",
"AutoDownloadSettings.TypeGroupChats": "Groups",
"AutoDownloadSettings.TypeChannels": "Channels",
};
export default lang;

20
src/lib/appManagers/appImManager.ts

@ -318,25 +318,7 @@ export class AppImManager { @@ -318,25 +318,7 @@ export class AppImManager {
const chat = this.chat;
if(e.key === 'Escape') {
let cancel = true;
if(this.markupTooltip?.container?.classList.contains('is-visible')) {
this.markupTooltip.hide();
} else if(chat.selection.isSelecting) {
chat.selection.cancelSelection();
} else if(chat.container.classList.contains('is-helper-active')) {
chat.input.replyElements.cancelBtn.click();
} else if(chat.peerId !== 0) { // hide current dialog
this.setPeer(0);
} else {
cancel = false;
}
// * cancel event for safari, because if application is in fullscreen, browser will try to exit fullscreen
if(cancel) {
cancelEvent(e);
}
} else if(e.key === 'Meta' || e.key === 'Control') {
if(e.key === 'Meta' || e.key === 'Control') {
return;
} else if(e.code === "KeyC" && (e.ctrlKey || e.metaKey) && target.tagName !== 'INPUT') {
return;

96
src/lib/langPack.ts

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
import { MOUNT_CLASS_TO } from "../config/debug";
import { safeAssign } from "../helpers/object";
import type lang from "../lang";
import { LangPackDifference, LangPackString } from "../layer";
import apiManager from "./mtproto/mtprotoworker";
import sessionStorage from "./sessionStorage";
@ -34,37 +35,7 @@ export const langPack: {[actionType: string]: string} = { @@ -34,37 +35,7 @@ export const langPack: {[actionType: string]: string} = {
"messageActionBotAllowed": "You allowed this bot to message you when logged in {}"
};
namespace Strings {
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' | 'Telegram.NotificationSettingsViewController' | 'Telegram.LanguageViewController';
export type ChatList = ChatListFilter;
export type ChatListAdd = 'ChatList.Add.TopSeparator' | 'ChatList.Add.BottomSeparator';
export type ChatListFilterIncluded = 'ChatList.Filter.Include.Header' | 'ChatList.Filter.Include.AddChat';
export type ChatListFilterExcluded = 'ChatList.Filter.Exclude.Header' | 'ChatList.Filter.Exclude.AddChat';
export type ChatListFilterList = 'ChatList.Filter.List.Header' | 'ChatList.Filter.List.Title';
export type ChatListFilterRecommended = 'ChatList.Filter.Recommended.Header' | 'ChatList.Filter.Recommended.Add';
export type ChatListFilter = ChatListAdd | ChatListFilterIncluded | ChatListFilterExcluded | ChatListFilterList | ChatListFilterRecommended | 'ChatList.Filter.Header' | 'ChatList.Filter.NewTitle' | 'ChatList.Filter.NonContacts' | 'ChatList.Filter.Contacts' | 'ChatList.Filter.Groups' | 'ChatList.Filter.Channels' | 'ChatList.Filter.Bots';
export type AutoDownloadSettings = 'AutoDownloadSettings.TypePrivateChats' | 'AutoDownloadSettings.TypeChannels';
export type DataAndStorage = 'DataAndStorage.CategorySettings.GroupChats';
export type Suggest = 'Suggest.Localization.Other';
export type UsernameSettings = 'UsernameSettings.ChangeDescription';
export type LangPackKey = string | AccountSettings | EditAccount | Telegram | ChatList | LoginRegister | Bio | AutoDownloadSettings | DataAndStorage | Suggest | UsernameSettings;
}
export type LangPackKey = Strings.LangPackKey;
export type LangPackKey = string | keyof typeof lang;
namespace I18n {
export const strings: Map<LangPackKey, LangPackString> = new Map();
@ -76,7 +47,7 @@ namespace I18n { @@ -76,7 +47,7 @@ namespace I18n {
sessionStorage.get('langPack'),
polyfillPromise
]).then(([langPack]) => {
if(!langPack) {
if(!langPack || true) {
return getLangPack('en');
}
@ -96,8 +67,40 @@ namespace I18n { @@ -96,8 +67,40 @@ namespace I18n {
lang_code: langCode,
lang_pack: 'macos'
}),
apiManager.invokeApi('langpack.getLangPack', {
lang_code: langCode,
lang_pack: 'android'
}),
import('../lang'),
polyfillPromise
]).then(([langPack, _]) => {
]).then(([langPack, _langPack, __langPack, _]) => {
let strings: LangPackString[] = [];
for(const i in __langPack.default) {
// @ts-ignore
const v = __langPack.default[i];
if(typeof(v) === 'string') {
strings.push({
_: 'langPackString',
key: i,
value: v
});
} else {
strings.push({
_: 'langPackStringPluralized',
key: i,
...v
});
}
}
strings = strings.concat(langPack.strings);
for(const string of _langPack.strings) {
strings.push(string);
}
langPack.strings = strings;
return sessionStorage.set({langPack}).then(() => {
applyLangPack(langPack);
return langPack;
@ -106,7 +109,7 @@ namespace I18n { @@ -106,7 +109,7 @@ namespace I18n {
}
export const polyfillPromise = (function checkIfPolyfillNeeded() {
if(typeof(Intl) !== 'undefined' && typeof(Intl.PluralRules) !== 'undefined'/* && false */) {
if(typeof(Intl) !== 'undefined' && typeof(Intl.PluralRules) !== 'undefined' && false) {
return Promise.resolve();
} else {
return import('./pluralPolyfill').then(_Intl => {
@ -143,24 +146,28 @@ namespace I18n { @@ -143,24 +146,28 @@ namespace I18n {
let out = '';
if(str) {
if(str._ === 'langPackStringPluralized') {
if(str._ === 'langPackStringPluralized' && args?.length) {
const v = args[0] as number;
const s = pluralRules.select(v);
// @ts-ignore
out = str[s + '_value'];
out = str[s + '_value'] || str['other_value'];
} else if(str._ === 'langPackString') {
out = str.value;
} else {
//out = '[' + key + ']';
out = key;
out = '[' + key + ']';
//out = key;
}
} else {
//out = '[' + key + ']';
out = key;
out = '[' + key + ']';
//out = key;
}
out = out
.replace(/\n/g, '<br>')
.replace(/\*\*(.+?)\*\*/g, '<b>$1</b>');
if(args?.length) {
out = out.replace(/%./g, (match, offset, string) => {
out = out.replace(/%\d\$.|%./g, (match, offset, string) => {
return '' + args.shift();
});
}
@ -172,7 +179,7 @@ namespace I18n { @@ -172,7 +179,7 @@ namespace I18n {
export type IntlElementOptions = {
element?: HTMLElement,
property?: 'innerText' | 'innerHTML' | 'placeholder'
property?: /* 'innerText' | */'innerHTML' | 'placeholder'
key: LangPackKey,
args?: any[]
};
@ -180,7 +187,7 @@ namespace I18n { @@ -180,7 +187,7 @@ namespace I18n {
public element: IntlElementOptions['element'];
public key: IntlElementOptions['key'];
public args: IntlElementOptions['args'];
public property: IntlElementOptions['property'] = 'innerText';
public property: IntlElementOptions['property'] = 'innerHTML';
constructor(options: IntlElementOptions) {
this.element = options.element || document.createElement('span');
@ -193,7 +200,8 @@ namespace I18n { @@ -193,7 +200,8 @@ namespace I18n {
public update(options?: IntlElementOptions) {
safeAssign(this, options);
(this.element as any)[this.property] = getString(this.key, this.args);
const str = getString(this.key, this.args);
(this.element as any)[this.property] = str;
}
}

Loading…
Cancel
Save