From 5b031b8d8426f9c987621892a7d0696ba8b1d168 Mon Sep 17 00:00:00 2001 From: Louis Delbosc Date: Thu, 26 Jan 2023 18:08:44 +0100 Subject: [PATCH 01/14] Change link to reference new when rowId is null --- app/client/components/BaseView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/client/components/BaseView.js b/app/client/components/BaseView.js index 8d63d79f..bba84c5d 100644 --- a/app/client/components/BaseView.js +++ b/app/client/components/BaseView.js @@ -141,7 +141,7 @@ function BaseView(gristDoc, viewSectionModel, options) { }).extend({deferred: true})); // Update the cursor whenever linkedRowId() changes. - this.autoDispose(this.linkedRowId.subscribe(rowId => this.setCursorPos({rowId}))); + this.autoDispose(this.linkedRowId.subscribe(rowId => this.setCursorPos({rowId: rowId || 'new'}))); // Indicated whether editing the section should be disabled given the current linking state. this.disableEditing = this.autoDispose(ko.computed(() => { From 84353bfef73643abe388742389482997aadb3176 Mon Sep 17 00:00:00 2001 From: newturok Date: Wed, 1 Feb 2023 17:49:31 +0100 Subject: [PATCH 02/14] Added translation using Weblate (Ukrainian) --- static/locales/uk.client.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 static/locales/uk.client.json diff --git a/static/locales/uk.client.json b/static/locales/uk.client.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/static/locales/uk.client.json @@ -0,0 +1 @@ +{} From 01ae637b83573dde7a3109ee2a5fdbbb098112aa Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Wed, 1 Feb 2023 12:53:37 +0000 Subject: [PATCH 03/14] Translated using Weblate (French) Currently translated at 97.5% (690 of 707 strings) Translation: Grist/client Translate-URL: https://hosted.weblate.org/projects/grist/client/fr/ --- static/locales/fr.client.json | 134 ++++++++++++++++++++++++++++++++-- 1 file changed, 126 insertions(+), 8 deletions(-) diff --git a/static/locales/fr.client.json b/static/locales/fr.client.json index 15b41fe8..cfb8135d 100644 --- a/static/locales/fr.client.json +++ b/static/locales/fr.client.json @@ -5,7 +5,7 @@ "We'll email an invite to {{email}}": "Nous allons envoyer une invitation à {{email}}" }, "AccessRules": { - "Checking...": "Vérification en cours…", + "Checking...": "Vérification…", "Saved": "Enregistré", "Invalid": "Invalide", "Save": "Enregistrer", @@ -32,12 +32,15 @@ "Attribute name": "Nom de l’attribut", "Everyone": "Tout le monde", "Everyone Else": "Tous les autres", - "Type a message...": "Type a message...", + "Type a message...": "Ajouter un message…", "Enter Condition": "Entrer la condition", "Remove {{- name }} user attribute": "Supprimer l'attribut utilisateur {{-name}}", "Remove {{- tableId }} rules": "Supprimer les règles pour la table {{-tableId}}", "View As": "Voir en tant que", - "Remove column {{- colId }} from {{- tableId }} rules": "Supprimer la colonne {{-colId}} des règles de la table {{-tableId}}" + "Remove column {{- colId }} from {{- tableId }} rules": "Supprimer la colonne {{-colId}} des règles de la table {{-tableId}}", + "Seed rules": "Règles par défaut", + "When adding table rules, automatically add a rule to grant OWNER full access.": "Ajouter automatiquement une règle donnant tous les droits au groupe OWNER.", + "Permission to edit document structure": "Droits d'édition de la structure" }, "AccountPage": { "Account settings": "Paramètres du compte", @@ -54,7 +57,8 @@ "Two-factor authentication is an extra layer of security for your Grist account designed to ensure that you're the only person who can access your account, even if someone knows your password.": "L'authentification à double facteur est une couche additionnelle de sécurité pour votre compte Grist qui permet de s'assurer que vous êtes la seule personne qui peut accéder à votre compte, même si quelqu'un d'autre connaît votre mot de passe.", "Theme": "Thème", "API Key": "Clé d’API", - "Names only allow letters, numbers and certain special characters": "Les noms d'utilisateurs ne doivent contenir que des lettres, des chiffres, et certains caractères spéciaux" + "Names only allow letters, numbers and certain special characters": "Les noms d'utilisateurs ne doivent contenir que des lettres, des chiffres, et certains caractères spéciaux", + "Language": "Langue" }, "AccountWidget": { "Sign in": "Connexion", @@ -261,7 +265,9 @@ "Engine (experimental {{span}} change at own risk):": "Moteur (expérimental {{span}} changez à vos risques et périls):", "Save": "Enregistrer", "Save and Reload": "Enregistrer et recharger", - "Document ID copied to clipboard": "Identifiant de document copié" + "Document ID copied to clipboard": "Identifiant de document copié", + "API": "API", + "Ok": "Ok" }, "DocumentUsage": { "Usage statistics are only available to users with full access to the document data.": "Les statistiques d'utilisation ne sont disponibles qu'aux utilisateurs ayant un accès complet aux données du document.", @@ -330,7 +336,8 @@ }, "FilterBar": { "SearchColuns": "Rechercher", - "SearchColumns": "Colonnes" + "SearchColumns": "Colonnes", + "Search Columns": "Chercher des colonnes" }, "GridOptions": { "Grid Options": "Options de la grille", @@ -551,7 +558,7 @@ "Current Version": "Version actuelle", "Original": "Original", "Return to {{termToUse}}": "Revenir à {{termToUse}}", - "Replace {{termToUse}}...": "Remplacer {{termToUse}}...", + "Replace {{termToUse}}...": "Remplacer {{termToUse}}…", "Compare to {{termToUse}}": "Comparer avec {{termToUse}}", "Work on a Copy": "Travailler sur une copie", "Edit without affecting the original": "Éditer sans affecter l'original", @@ -595,7 +602,8 @@ "Delete document tour?": "Delete document tour?", "Delete": "Supprimer", "Return to viewing as yourself": "Revenir à une vue en propre", - "Raw Data": "Données source" + "Raw Data": "Données source", + "Settings": "Paramètres" }, "TopBar": { "Manage Team": "Gestion de l'équipe" @@ -764,5 +772,115 @@ }, "ViewAsBanner": { "UnknownUser": "Utilisateur inconnu" + }, + "CellStyle": { + "Open row styles": "Ouvrir les styles de ligne", + "Cell Style": "Style de cellule", + "CELL STYLE": "STYLE de CELLULE", + "Default cell style": "Style par défaut", + "Mixed style": "Style composite" + }, + "DiscussionEditor": { + "Comment": "Commentaire", + "Save": "Enregistrer", + "Open": "Ouvrir", + "Write a comment": "Écrire un commentaire", + "Cancel": "Annuler", + "Edit": "Modifier", + "Reply to a comment": "Répondre à un commentaire", + "Only current page": "Page actuelle uniquement", + "Remove": "Supprimer", + "Marked as resolved": "Marquer comme résolu", + "Only my threads": "Seulement mes fils", + "Reply": "Répondre", + "Show resolved comments": "Montrer les commentaires résolus", + "Resolve": "Résoudre", + "Showing last {{nb}} comments": "Montrer les {{nb}} commentaires", + "Started discussion": "Discussion commencée" + }, + "FieldBuilder": { + "Apply Formula to Data": "Appliquer une formule", + "DATA FROM TABLE": "DONNÉES DE LA TABLE", + "CELL FORMAT": "FORMAT DE CELLULE", + "Mixed types": "Types composites", + "Changing multiple column types": "Changer plusieurs types", + "Mixed format": "Format composite" + }, + "welcomeTour": { + "Customizing columns": "Personnaliser les colonnes", + "template library": "Bibliothèque de modèles", + "Share": "Partager", + "Add New": "Nouveau", + "Building up": "En construction", + "Configuring your document": "Configuration de votre document", + "Double-click or hit {{enter}} on a cell to edit it. ": "Double-cliquer ou appuyer sur {{enter}} sur une cellule pour la modifier ", + "Editing Data": "Modification des données", + "Welcome to Grist!": "Bienvenue sur Grist!", + "Start with {{equal}} to enter a formula.": "Commencer par {{equal}} pour ajouter une formule.", + "Sharing": "Partager", + "Reference": "Référence", + "Help Center": "Centre d'aide" + }, + "TypeTransformation": { + "Cancel": "Annuler", + "Apply": "Ok", + "Revise": "Amender", + "Preview": "Aperçu", + "Update formula (Shift+Enter)": "Modifier la formule (MAJ+Entrée)" + }, + "ColumnEditor": { + "COLUMN DESCRIPTION": "DESCRIPTION", + "COLUMN LABEL": "LIBELLÉ" + }, + "ACLUsers": { + "Example Users": "Utilisateurs tests", + "Users from table": "Utilisateurs de la table", + "View As": "Voir en tant que" + }, + "ConditionalStyle": { + "Add conditional style": "Ajouter un style conditionnel", + "Add another rule": "Ajouter une autre règle", + "Error in style rule": "Erreur dans la règle de style", + "Row Style": "Style de ligne", + "Rule must return True or False": "La règle doit retourner Vrai ou Faux" + }, + "CurrencyPicker": { + "Invalid currency": "Devise invalide" + }, + "ChoiceTextBox": { + "CHOICES": "CHOIX" + }, + "ColumnInfo": { + "COLUMN DESCRIPTION": "DESCRIPTION", + "COLUMN ID: ": "ID: ", + "COLUMN LABEL": "LIBELLÉ", + "Cancel": "Annuler", + "Save": "Enregistrer" + }, + "EditorTooltip": { + "Convert column to formula": "Convertir en formule" + }, + "FieldEditor": { + "Unable to finish saving edited cell": "Impossible de terminer l'enregistrement" + }, + "FormulaEditor": { + "Errors in all {{numErrors}} cells": "Erreur dans toutes les {{numErrors}} cellules", + "Error in the cell": "Erreur dans la cellule", + "Column or field is required": "Colonne ou champ requis", + "Errors in {{numErrors}} of {{numCells}} cells": "Erreur dans {{numErrors}} des {{numCells}} cellules" + }, + "NumericTextBox": { + "Decimals": "Décimales", + "Currency": "Devise", + "Default currency ({{defaultCurrency}})": "Devise par défaut ({{defaultCurrency}})", + "Number Format": "Format de nombre" + }, + "LanguageMenu": { + "Language": "Langue" + }, + "Reference": { + "Row ID": "Id de ligne", + "CELL FORMAT": "FORMAT DE CELLULE", + "SHOW COLUMN": "MONTRER LA COLONNE" } } From 5e9fe8ec0a597451c386f7c70fffb5bbbd788573 Mon Sep 17 00:00:00 2001 From: Paul Janzen Date: Wed, 1 Feb 2023 14:55:02 +0000 Subject: [PATCH 04/14] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (707 of 707 strings) Translation: Grist/client Translate-URL: https://hosted.weblate.org/projects/grist/client/pt_BR/ --- static/locales/pt_BR.client.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/static/locales/pt_BR.client.json b/static/locales/pt_BR.client.json index 64bd30ba..121f3779 100644 --- a/static/locales/pt_BR.client.json +++ b/static/locales/pt_BR.client.json @@ -57,7 +57,8 @@ "Save": "Salvar", "Theme": "Tema", "Two-factor authentication": "Autenticação de dois fatores", - "Two-factor authentication is an extra layer of security for your Grist account designed to ensure that you're the only person who can access your account, even if someone knows your password.": "A autenticação de dois fatores é uma camada extra de segurança para sua conta Grist projetada para garantir que você seja a única pessoa que pode acessar sua conta, mesmo que alguém saiba sua senha." + "Two-factor authentication is an extra layer of security for your Grist account designed to ensure that you're the only person who can access your account, even if someone knows your password.": "A autenticação de dois fatores é uma camada extra de segurança para sua conta Grist projetada para garantir que você seja a única pessoa que pode acessar sua conta, mesmo que alguém saiba sua senha.", + "Language": "Idioma" }, "AccountWidget": { "Access Details": "Detalhes de Acesso", @@ -959,5 +960,8 @@ }, "ChoiceTextBox": { "CHOICES": "ESCOLHAS" + }, + "LanguageMenu": { + "Language": "Idioma" } } From 358d531ea3f2ea4770220a4ed9614fc5d7e2d921 Mon Sep 17 00:00:00 2001 From: gallegonovato Date: Wed, 1 Feb 2023 14:53:14 +0000 Subject: [PATCH 05/14] Translated using Weblate (Spanish) Currently translated at 100.0% (707 of 707 strings) Translation: Grist/client Translate-URL: https://hosted.weblate.org/projects/grist/client/es/ --- static/locales/es.client.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/static/locales/es.client.json b/static/locales/es.client.json index fd78adb8..8b8bdf7a 100644 --- a/static/locales/es.client.json +++ b/static/locales/es.client.json @@ -52,7 +52,8 @@ "Save": "Guardar", "Theme": "Tema", "Two-factor authentication": "Autenticación de dos factores", - "Two-factor authentication is an extra layer of security for your Grist account designed to ensure that you're the only person who can access your account, even if someone knows your password.": "La autenticación de dos factores provee seguridad adicional para su cuenta Grist, diseñada para garantizar que usted sea la única persona que pueda acceder a su cuenta, incluso si alguien conoce su contraseña." + "Two-factor authentication is an extra layer of security for your Grist account designed to ensure that you're the only person who can access your account, even if someone knows your password.": "La autenticación de dos factores provee seguridad adicional para su cuenta Grist, diseñada para garantizar que usted sea la única persona que pueda acceder a su cuenta, incluso si alguien conoce su contraseña.", + "Language": "Idioma" }, "AccountWidget": { "Access Details": "Detalles de Acceso", @@ -949,5 +950,8 @@ "SHOW COLUMN": "MOSTRAR COLUMNA", "CELL FORMAT": "FORMATO DE CELDA", "Row ID": "ID de fila" + }, + "LanguageMenu": { + "Language": "Idioma" } } From 4fbd492b5bffbf21029439ed6c00fbe1cd760fa3 Mon Sep 17 00:00:00 2001 From: Paul Janzen Date: Wed, 1 Feb 2023 14:56:04 +0000 Subject: [PATCH 06/14] Translated using Weblate (German) Currently translated at 100.0% (707 of 707 strings) Translation: Grist/client Translate-URL: https://hosted.weblate.org/projects/grist/client/de/ --- static/locales/de.client.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/static/locales/de.client.json b/static/locales/de.client.json index 0f400bde..405a35ca 100644 --- a/static/locales/de.client.json +++ b/static/locales/de.client.json @@ -57,7 +57,8 @@ "Save": "Speichern", "Theme": "Thema", "Two-factor authentication": "Zwei-Faktor-Authentifizierung", - "Two-factor authentication is an extra layer of security for your Grist account designed to ensure that you're the only person who can access your account, even if someone knows your password.": "Die Zwei-Faktor-Authentifizierung ist eine zusätzliche Sicherheitsebene für Ihr Grist-Konto, die sicherstellt, dass Sie die einzige Person sind, die auf Ihr Konto zugreifen kann, selbst wenn jemand Ihr Passwort kennt." + "Two-factor authentication is an extra layer of security for your Grist account designed to ensure that you're the only person who can access your account, even if someone knows your password.": "Die Zwei-Faktor-Authentifizierung ist eine zusätzliche Sicherheitsebene für Ihr Grist-Konto, die sicherstellt, dass Sie die einzige Person sind, die auf Ihr Konto zugreifen kann, selbst wenn jemand Ihr Passwort kennt.", + "Language": "Sprache" }, "AccountWidget": { "Access Details": "Zugangsdetails", @@ -959,5 +960,8 @@ "FieldEditor": { "It should be impossible to save a plain data value into a formula column": "Es sollte unmöglich sein, einen einfachen Datenwert in eine Formelspalte zu speichern", "Unable to finish saving edited cell": "Speichern der bearbeiteten Zelle kann nicht abgeschlossen werden" + }, + "LanguageMenu": { + "Language": "Sprache" } } From 42c560ca05242edecc42113b52411cc1f6e7204e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D0=BC=D0=B8=D1=80=20=D0=92?= Date: Wed, 1 Feb 2023 11:20:32 +0000 Subject: [PATCH 07/14] Translated using Weblate (Russian) Currently translated at 18.8% (133 of 707 strings) Translation: Grist/client Translate-URL: https://hosted.weblate.org/projects/grist/client/ru/ --- static/locales/ru.client.json | 177 +++++++++++++++++++++++++++++++++- 1 file changed, 176 insertions(+), 1 deletion(-) diff --git a/static/locales/ru.client.json b/static/locales/ru.client.json index 0967ef42..8e72a437 100644 --- a/static/locales/ru.client.json +++ b/static/locales/ru.client.json @@ -1 +1,176 @@ -{} +{ + "AccessRules": { + "Allow everyone to view Access Rules.": "Разрешить всем просматривать правила доступа.", + "Attribute name": "Имя атрибута", + "Add Default Rule": "Добавить правило по умолчанию", + "Add Column Rule": "Добавить правило столбца", + "View As": "Посмотреть как", + "Seed rules": "Наследуемые правила", + "Add User Attributes": "Добавить атрибуты пользователя", + "Add Table Rules": "Добавить правила таблицы", + "Everyone": "Остальные", + "Delete Table Rules": "Удалить правила таблицы", + "Enter Condition": "Введите условие", + "Lookup Column": "Столбец поиска", + "Everyone Else": "Все остальные", + "Remove {{- name }} user attribute": "Удалить атрибут пользователя {{- name }}", + "Invalid": "Недействительный", + "Permission to access the document in full when needed": "Разрешение на полный доступ к документу при необходимости", + "Remove {{- tableId }} rules": "Удалить правила {{- tableId }}", + "Allow everyone to copy the entire document, or view it in full in fiddle mode.\nUseful for examples and templates, but not for sensitive data.": "Разрешить всем копировать весь документ, или посмотреть его полностью в режиме Форк (fiddle).\nПолезно для примеров и шаблонов, но не для конфиденциальных данных.", + "Attribute to Look Up": "Атрибут для поиска (Look Up)", + "Condition": "Условие", + "Checking...": "Проверка…", + "Default Rules": "Правила по умолчанию", + "Lookup Table": "Таблица поиска", + "Permission to view Access Rules": "Разрешение на просмотр правил доступа", + "Permissions": "Разрешения", + "Remove column {{- colId }} from {{- tableId }} rules": "Удалить столбец {{- colId }} из правил {{- tableId }}", + "Reset": "Сброс", + "Rules for table ": "Правила для таблицы ", + "Save": "Сохранить", + "Special Rules": "Специальные правила", + "User Attributes": "Пользовательские атрибуты", + "Type a message...": "Введите сообщение…", + "Saved": "Сохранено", + "Permission to edit document structure": "Разрешение на редактирование структуры документа", + "When adding table rules, automatically add a rule to grant OWNER full access.": "При добавлении правил таблицы, автоматически добавить правило для предоставления ВЛАДЕЛЬЦУ полного доступа." + }, + "ACUserManager": { + "Enter email address": "Введите адрес электронной почты", + "Invite new member": "Пригласить нового участника", + "We'll email an invite to {{email}}": "Мы вышлем приглашение на {{email}}" + }, + "AccountPage": { + "API": "API", + "Allow signing in to this account with Google": "Разрешить вход в этот аккаунт с помощью Google", + "Theme": "Тема", + "Change Password": "Изменить пароль", + "API Key": "API Ключ", + "Account settings": "Настройки аккаунта", + "Edit": "Редактировать", + "Name": "Имя", + "Email": "Email", + "Login Method": "Способ входа в систему", + "Names only allow letters, numbers and certain special characters": "В именах допускаются только буквы, цифры и определенные специальные символы", + "Save": "Сохранить", + "Password & Security": "Пароль & Безопасность", + "Two-factor authentication": "Двухфакторная аутентификация", + "Two-factor authentication is an extra layer of security for your Grist account designed to ensure that you're the only person who can access your account, even if someone knows your password.": "Двухфакторная аутентификация - это дополнительный уровень безопасности для вашей учетной записи Grist, предназначенный для идентификации вас как единственного человека, который может получить доступ к вашей учетной записи, даже если кто-то знает ваш пароль.", + "Language": "Язык" + }, + "App": { + "Memory Error": "Ошибка памяти", + "Description": "Описание", + "Key": "Ключ" + }, + "ColorSelect": { + "Apply": "Применить", + "Cancel": "Отменить", + "Default cell style": "Стиль ячейки по умолчанию" + }, + "ColumnFilterMenu": { + "Max": "Max", + "Start": "Начинается", + "End": "Оканчивается", + "Other Non-Matching": "Другие несоответствующие", + "None": "None", + "All Except": "Все, кроме", + "All": "Все", + "All Shown": "Все отображенное", + "Filter by Range": "Фильтровать по диапазону", + "Future Values": "Будущие значения", + "No matching values": "Нет совпадающих значений", + "Min": "Min", + "Other Values": "Другие значения", + "Other Matching": "Другие соответствующие", + "Others": "Другие", + "Search": "Поиск", + "Search values": "Поиск значений" + }, + "AppHeader": { + "Personal Site": "Личный сайт", + "Home Page": "Домашняя страница", + "Legacy": "Устаревший", + "Team Site": "Сайт группы" + }, + "ApiKey": { + "Remove API Key": "Удалить ключ API", + "This API key can be used to access this account anonymously via the API.": "Этот ключ API можно использовать для анонимного доступа к этой учетной записи через API.", + "You're about to delete an API key. This will cause all future requests using this API key to be rejected. Do you still want to delete?": "Вы собираетесь удалить ключ API. Это приведет к отклонению всех будущих запросов, использующих этот ключ API. Вы все еще хотите удалить?", + "Create": "Создать", + "This API key can be used to access your account via the API. Don’t share your API key with anyone.": "Этот ключ API можно использовать для доступа к вашей учетной записи через API. Никому не сообщайте свой ключ API.", + "Remove": "Удалить", + "By generating an API key, you will be able to make API calls for your own account.": "Сгенерировав ключ API, вы сможете выполнять вызовы API для своей собственной учетной записи.", + "Click to show": "Нажмите, чтобы показать" + }, + "CellContextMenu": { + "Clear cell": "Очистить ячейку", + "Delete {{count}} rows_one": "Удалить строку", + "Clear values": "Очистить значения", + "Copy anchor link": "Скопировать якорную ссылку", + "Delete {{count}} rows_other": "Удалить {{count}} строки", + "Delete {{count}} columns_one": "Удалить столбец", + "Delete {{count}} columns_other": "Удалить {{count}} столбцы", + "Duplicate rows_one": "Дублировать строку", + "Insert column to the left": "Вставить столбец слева", + "Duplicate rows_other": "Дублировать строки", + "Filter by this value": "Фильтровать по этому значению", + "Insert column to the right": "Вставить столбец справа", + "Insert row": "Вставить строку", + "Insert row above": "Вставить строку выше", + "Insert row below": "Вставить строку ниже", + "Reset {{count}} columns_one": "Сбросить столбец", + "Reset {{count}} columns_other": "Сброс {{count}} столбцов", + "Reset {{count}} entire columns_one": "Сбросить весь столбец", + "Reset {{count}} entire columns_other": "Сброс всех {{count}} столбцов" + }, + "AppModel": { + "This team site is suspended. Documents can be read, but not modified.": "Этот сайт группы приостановлен. Документы можно читать, но не изменять." + }, + "ChartView": { + "Each Y series is followed by a series for the length of error bars.": "Each Y series is followed by a series for the length of error bars.", + "Each Y series is followed by two series, for top and bottom error bars.": "Each Y series is followed by two series, for top and bottom error bars.", + "Create separate series for each value of the selected column.": "Создайте отдельные ряды для каждого значения выбранного столбца.", + "selected new group data columns": "выбранные новые группы столбцов данных", + "Pick a column": "Выберите столбец", + "Toggle chart aggregation": "Переключение агрегации диаграмм" + }, + "CodeEditorPanel": { + "Access denied": "Доступ запрещен", + "Code View is available only when you have full document access.": "Просмотр кода доступен, только если у вас есть полный доступ к документу." + }, + "CustomSectionConfig": { + " (optional)": " (опционально)", + "Add": "Добавить", + "Enter Custom URL": "Введите пользовательский URL", + "Full document access": "Полный доступ к документу" + }, + "AccountWidget": { + "Access Details": "Сведения о доступе", + "Accounts": "Аккаунты", + "Document Settings": "Настройки документа", + "Profile Settings": "Настройки профиля", + "Switch Accounts": "Переключить аккаунты", + "Add Account": "Добавить аккаунт", + "Manage Team": "Управление командой", + "Sign in": "Войти", + "Toggle Mobile Mode": "Переключить мобильный режим", + "Pricing": "Цены", + "Sign Out": "Выход" + }, + "ActionLog": { + "Table {{tableId}} was subsequently removed in action #{{actionNum}}": "Таблица {{tableId}} впоследствии была удалена в действии #{{actionNum}}", + "Action Log failed to load": "Не удалось загрузить журнал действий", + "Column {{colId}} was subsequently removed in action #{{action.actionNum}}": "Столбец {{colId}} впоследствии был удален в действии #{{action.actionNum}}", + "This row was subsequently removed in action {{action.actionNum}}": "Эта строка впоследствии была удалена в действии {{action.actionNum}}" + }, + "ViewAsDropdown": { + "Example Users": "Пользователи для примеров", + "View As": "Посмотреть как", + "Users from table": "Пользователи из таблицы" + }, + "AddNewButton": { + "Add New": "Добавить" + } +} From 4550058984ca1f844c397ed9c93fa05cb593123c Mon Sep 17 00:00:00 2001 From: Paul Fitzpatrick Date: Wed, 1 Feb 2023 14:01:47 -0500 Subject: [PATCH 08/14] v1.0.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c88fefbf..450819db 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "grist-core", - "version": "1.0.6", + "version": "1.0.7", "license": "Apache-2.0", "description": "Grist is the evolution of spreadsheets", "homepage": "https://github.com/gristlabs/grist-core", From 046222b1d9b6f4840c4121686b32b1be2864d4e0 Mon Sep 17 00:00:00 2001 From: George Gevoian <85144792+georgegevoian@users.noreply.github.com> Date: Wed, 1 Feb 2023 15:19:15 -0500 Subject: [PATCH 09/14] Show language prefs when custom CSS is enabled (#418) --- app/client/ui/AccountPage.ts | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/app/client/ui/AccountPage.ts b/app/client/ui/AccountPage.ts index 5cc5f6d9..88d95ad8 100644 --- a/app/client/ui/AccountPage.ts +++ b/app/client/ui/AccountPage.ts @@ -137,20 +137,18 @@ export class AccountPage extends Disposable { ), dom.create(MFAConfig, user), ), + css.header(t("Theme")), // Custom CSS is incompatible with custom themes. - enableCustomCss ? null : [ - css.header(t("Theme")), - dom.create(ThemeConfig, this._appModel), - css.subHeader(t("Language")), - css.dataRow({ style: 'width: 300px'}, - select(userLocale, languageOptions, { - renderOptionArgs: () => { - return dom.cls(cssFirstUpper.className); - } - }), - testId('language'), - ) - ], + enableCustomCss ? null : dom.create(ThemeConfig, this._appModel), + css.subHeader(t("Language")), + css.dataRow({ style: 'width: 300px'}, + select(userLocale, languageOptions, { + renderOptionArgs: () => { + return dom.cls(cssFirstUpper.className); + } + }), + testId('language'), + ), css.header(t("API")), css.dataRow(css.inlineSubHeader(t("API Key")), css.content( dom.create(ApiKey, { From 8480a872ff19da4afb222b9de391955468052d07 Mon Sep 17 00:00:00 2001 From: Louis Delbosc Date: Thu, 2 Feb 2023 09:54:36 +0100 Subject: [PATCH 10/14] Add test --- .../docs/Favorite_Films_With_Linked_Ref.grist | Bin 0 -> 324608 bytes test/nbrowser/ReferenceColumns.ts | 19 +++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 test/fixtures/docs/Favorite_Films_With_Linked_Ref.grist diff --git a/test/fixtures/docs/Favorite_Films_With_Linked_Ref.grist b/test/fixtures/docs/Favorite_Films_With_Linked_Ref.grist new file mode 100644 index 0000000000000000000000000000000000000000..f08e57125b83a51a2140cda396fd066f64ab755a GIT binary patch literal 324608 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 literal 0 HcmV?d00001 diff --git a/test/nbrowser/ReferenceColumns.ts b/test/nbrowser/ReferenceColumns.ts index 205d247f..c3c83a75 100644 --- a/test/nbrowser/ReferenceColumns.ts +++ b/test/nbrowser/ReferenceColumns.ts @@ -11,7 +11,7 @@ describe('ReferenceColumns', function() { describe('rendering', function() { before(async function() { session = await gu.session().teamSite.login(); - await session.tempDoc(cleanup, 'Favorite_Films.grist'); + await session.tempDoc(cleanup, 'Favorite_Films_With_Linked_Ref.grist'); await gu.toggleSidePanel('right'); await driver.find('.test-config-data').click(); @@ -147,6 +147,23 @@ describe('ReferenceColumns', function() { ] ); }); + + it('should have linked card for friends', async () => { + // Open the All page. + await driver.findContentWait('.test-treeview-itemHeader', /Linked Friends/, 2000).click(); + await gu.waitForDocToLoad(); + + await driver.findContentWait('.field_clip', /Mary/, 2000).click(); + await gu.waitForServer(); + await driver.findContentWait('.g_record_detail_label', /Title/, 2000).click(); + assert.equal(await gu.getActiveCell().getText(), 'Alien'); + + await driver.findContentWait('.field_clip', /Jarek/, 2000).click(); + await gu.waitForServer(); + await driver.findContentWait('.g_record_detail_label', /Title/, 2000).click(); + assert.equal(await gu.getActiveCell().getText(), ''); + + }); }); describe('autocomplete', function() { From 2128316a44cf70382dd1d550295a043b6155a51a Mon Sep 17 00:00:00 2001 From: Przemek Date: Fri, 3 Feb 2023 13:57:39 +0100 Subject: [PATCH 11/14] Added translation using Weblate (Polish) --- static/locales/pl.client.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 static/locales/pl.client.json diff --git a/static/locales/pl.client.json b/static/locales/pl.client.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/static/locales/pl.client.json @@ -0,0 +1 @@ +{} From 1f2bdd68e92fcd1d735d4e3ba5d30908ff02b3cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rog=C3=A9rio=20Penna?= Date: Wed, 1 Feb 2023 17:17:54 +0000 Subject: [PATCH 12/14] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (707 of 707 strings) Translation: Grist/client Translate-URL: https://hosted.weblate.org/projects/grist/client/pt_BR/ --- static/locales/pt_BR.client.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/static/locales/pt_BR.client.json b/static/locales/pt_BR.client.json index 121f3779..04f067aa 100644 --- a/static/locales/pt_BR.client.json +++ b/static/locales/pt_BR.client.json @@ -243,8 +243,8 @@ "Restore": "Restaurar", "This service is not available right now": "Este serviço não está disponível no momento", "To restore this document, restore the workspace first.": "Para restaurar esse documento, restaure a área de trabalho primeiro.", - "Trash": "Lixo", - "Trash is empty.": "O lixo está vazio.", + "Trash": "Lixeira", + "Trash is empty.": "O lixeira está vazia.", "Unpin Document": "Desafixar o Documento", "Workspace not found": "Área de trabalho não encontrada", "You are on the {{siteName}} site. You also have access to the following sites:": "Você está no site {{siteName}}. Você também tem acesso aos seguintes sites:", @@ -447,7 +447,7 @@ "Import Document": "Importar Documento", "Manage Users": "Gerenciar Usuários", "Rename": "Renomear", - "Trash": "Lixo", + "Trash": "Lixeira", "Workspace will be moved to Trash.": "A Área de Trabalho será movida à Lixeira.", "Workspaces": "Áreas de Trabalho" }, From 13a0a44552f495738a865f8feead65ae25598867 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BB=D0=B0=D0=B4=D0=B8=D0=BC=D0=B8=D1=80=20=D0=92?= Date: Thu, 2 Feb 2023 21:29:19 +0000 Subject: [PATCH 13/14] Translated using Weblate (Russian) Currently translated at 73.5% (520 of 707 strings) Translation: Grist/client Translate-URL: https://hosted.weblate.org/projects/grist/client/ru/ --- static/locales/ru.client.json | 495 +++++++++++++++++++++++++++++++++- 1 file changed, 493 insertions(+), 2 deletions(-) diff --git a/static/locales/ru.client.json b/static/locales/ru.client.json index 8e72a437..5a613340 100644 --- a/static/locales/ru.client.json +++ b/static/locales/ru.client.json @@ -74,7 +74,7 @@ "Start": "Начинается", "End": "Оканчивается", "Other Non-Matching": "Другие несоответствующие", - "None": "None", + "None": "Нет", "All Except": "Все, кроме", "All": "Все", "All Shown": "Все отображенное", @@ -144,7 +144,19 @@ " (optional)": " (опционально)", "Add": "Добавить", "Enter Custom URL": "Введите пользовательский URL", - "Full document access": "Полный доступ к документу" + "Full document access": "Полный доступ к документу", + "Widget needs to {{read}} the current table.": "Виджет должен {{read}} текущую таблицу.", + "Widget needs {{fullAccess}} to this document.": "Виджет должен {{fullAccess}} для этого документа.", + "{{wrongTypeCount}} non-{{columnType}} columns are not shown_other": "{{wrongTypeCount}} не-{{columnType}} столбец не отображается", + "{{wrongTypeCount}} non-{{columnType}} columns are not shown_one": "{{wrongTypeCount}} не-{{columnType}} столбец не отображается", + "Learn more about custom widgets": "Узнайте больше о пользовательских виджетах", + "Pick a {{columnType}} column": "Выберать {{columnType}} столбец", + "No document access": "Нет доступа к документу", + "Open configuration": "Открыть конфигурацию", + "Select Custom Widget": "Выбор пользовательского виджета", + "Pick a column": "Выберать столбец", + "Read selected table": "Просмотр выбранной таблицы", + "Widget does not require any permissions.": "Виджет не требует никаких разрешений." }, "AccountWidget": { "Access Details": "Сведения о доступе", @@ -172,5 +184,484 @@ }, "AddNewButton": { "Add New": "Добавить" + }, + "ValidationPanel": { + "Rule {{length}}": "Правило {{length}}", + "Update formula (Shift+Enter)": "Update formula (Shift+Enter)" + }, + "FieldBuilder": { + "Apply Formula to Data": "Применить формулу к данным" + }, + "FieldConfig": { + "TRIGGER FORMULA": "ТРИГГЕРНАЯ ФОРМУЛА", + "Column options are limited in summary tables.": "Параметры столбцов в сводных таблицах ограничены.", + "Clear and reset": "Очистка и сброс", + "COLUMN BEHAVIOR": "ПОВЕДЕНИЕ СТОЛБЦА", + "COLUMN LABEL AND ID": "ЯРЛЫК И ID СТОЛБЦА", + "Clear and make into formula": "Очистить и преобразовать в формулу", + "Convert column to data": "Преобразовать столбец в данные", + "Data Columns_one": "Столбец данных", + "Convert to trigger formula": "Преобразовать в триггерную формулу", + "Set trigger formula": "Задать триггерную формулу", + "Formula Columns_other": "Столбцы формул", + "Data Columns_other": "Столбцы данных", + "Empty Columns_one": "Пустой столбец", + "Empty Columns_other": "Пустые столбцы", + "Formula Columns_one": "Столбец формулы", + "Make into data column": "Преобразовать в столбец данных", + "Enter formula": "Введите формулу", + "Mixed Behavior": "Смешанное поведение", + "Set formula": "Задать формулу" + }, + "MakeCopyMenu": { + "Update Original": "Обновить оригинал", + "Be careful, the original has changes not in this document. Those changes will be overwritten.": "Будьте осторожны, в оригинале есть изменения, которых нет в этом документе. Эти изменения будут перезаписаны.", + "Enter document name": "Введите название документа", + "Name": "Наименование", + "As Template": "Как шаблон", + "Cancel": "Отмена", + "However, it appears to be already identical.": "Однако, похоже он уже идентичен.", + "Organization": "Организация", + "Original Has Modifications": "Оригинал Имеет Модификации", + "Include the structure without any of the data.": "Включите структуру без каких-либо данных.", + "Sign up": "Регистрация", + "Original Looks Identical": "Оригинал выглядит идентично", + "Workspace": "Рабочее пространство", + "It will be overwritten, losing any content not in this document.": "Он будет перезаписан, потеряв все содержимое, не входящее в этот документ.", + "Original Looks Unrelated": "Оригинал выглядит несвязанным", + "Update": "Обновить", + "No destination workspace": "Нет целевого рабочего пространства", + "The original version of this document will be updated.": "Первоначальная версия этого документа будет обновлена.", + "Overwrite": "Перезаписать", + "Replacing the original requires editing rights on the original document.": "Для замены оригинала требуются права на редактирование исходного документа.", + "To save your changes, please sign up, then reload this page.": "Чтобы сохранить изменения, пожалуйста зарегистрируйтесь, а затем перезагрузите эту страницу.", + "You do not have write access to the selected workspace": "У вас нет прав на запись в выбранное рабочее пространство", + "You do not have write access to this site": "У вас нет права записи для этого сайта" + }, + "ShareMenu": { + "Back to Current": "Вернуться к текущему", + "Show in folder": "Показать в папке", + "Return to {{termToUse}}": "Вернуться к {{termToUse}}", + "Unsaved": "Несохраненный", + "Export XLSX": "Экспорт XLSX", + "Access Details": "Детали доступа", + "Current Version": "Текущая версия", + "Replace {{termToUse}}...": "Заменить {{termToUse}}…", + "Duplicate Document": "Дублировать документ", + "Original": "Оригинал", + "Compare to {{termToUse}}": "Сравнить с {{termToUse}}", + "Download": "Скачать", + "Edit without affecting the original": "Редактировать, не затрагивая оригинал", + "Export CSV": "Экспорт CSV", + "Manage Users": "Управление пользователями", + "Save Copy": "Сохранить копию", + "Send to Google Drive": "Отправить в Google Диск", + "Save Document": "Сохранить документ", + "Work on a Copy": "Работа над копией" + }, + "SortConfig": { + "Search Columns": "Search columns", + "Add Column": "Добавить столбец", + "Empty values last": "Empty values last", + "Natural sort": "Natural sort", + "Update Data": "Обновить данные", + "Use choice position": "Use choice position" + }, + "SortFilterConfig": { + "Filter": "ФИЛЬТР", + "Revert": "Revert", + "Save": "Сохранить", + "Sort": "СОРТИРОВКА", + "Update Sort & Filter settings": "Обновить настройки Сортировки & Фильтра" + }, + "Tools": { + "Access Rules": "Правила доступа", + "Delete": "Удалить", + "Delete document tour?": "Удалить тур по документу?", + "Code View": "Просмотр кода", + "Document History": "История документа", + "How-to Tutorial": "Учебное пособие", + "Raw Data": "Исходные данные", + "Return to viewing as yourself": "Возврат к просмотру от своего имени", + "TOOLS": "ИНСТРУМЕНТЫ", + "Tour of this Document": "Тур по этому документу", + "Validate Data": "Проверка данных", + "Settings": "Настройки" + }, + "TypeTransformation": { + "Cancel": "Отмена", + "Revise": "Revise", + "Apply": "Применить", + "Preview": "Предпросмотр", + "Update formula (Shift+Enter)": "Update formula (Shift+Enter)" + }, + "DataTables": { + "Click to copy": "Нажмите для копирования", + "Raw Data Tables": "Необработанные данные таблиц", + "Duplicate Table": "Дублировать таблицу", + "Table ID copied to clipboard": "Идентификатор таблицы скопирован в буфер обмена", + "You do not have edit access to this document": "У вас нет доступа к редактированию этого документа", + "Delete {{formattedTableName}} data, and remove it from all pages?": "Удалить {{formattedTableName}} данные, и удалить их со всех страниц?" + }, + "DocHistory": { + "Snapshots": "Снимки", + "Activity": "Активность", + "Compare to Previous": "Сравните с предыдущим", + "Beta": "Beta", + "Compare to Current": "Сравните с текущим", + "Snapshots are unavailable.": "Снимки недоступны.", + "Open Snapshot": "Открыть Снимок" + }, + "DocMenu": { + "By Name": "По имени", + "(The organization needs a paid plan)": "(Организации необходим платный тариф)", + "Access Details": "Детали доступа", + "All Documents": "Все документы", + "By Date Modified": "По дате изменения", + "Delete Forever": "Удалить навсегда", + "Move {{name}} to workspace": "Переместить {{name}} в рабочее пространство", + "Delete": "Удалить", + "Current workspace": "Текущее рабочее пространство", + "Delete {{name}}": "Удалить {{name}}", + "Deleted {{at}}": "Удалено {{at}}", + "Examples and Templates": "Примеры и Шаблоны", + "Discover More Templates": "Поиск большего числа шаблонов", + "Edited {{at}}": "Отредактировано {{at}}", + "Document will be permanently deleted.": "Документ будет удален навсегда.", + "Documents stay in Trash for 30 days, after which they get deleted permanently.": "Документы остаются в Корзине в течение 30 дней, после чего удаляются навсегда.", + "Examples & Templates": "Примеры & Шаблоны", + "Featured": "Рекомендуемые", + "Manage Users": "Управление пользователями", + "Move": "Переместить", + "Other Sites": "Другие сайты", + "Permanently Delete \"{{name}}\"?": "Удалить навсегда \"{{name}}\"?", + "More Examples and Templates": "Больше Примеров и Шаблонов", + "Pinned Documents": "Закрепленные документы", + "Pin Document": "Закрепить документ", + "You are on the {{siteName}} site. You also have access to the following sites:": "Вы находитесь на {{siteName}} сайте. У вас также есть доступ к следующим сайтам:", + "Remove": "Удалить", + "Rename": "Переименовать", + "Requires edit permissions": "Требуются разрешения на редактирование", + "This service is not available right now": "Эта услуга сейчас недоступна", + "Restore": "Восстановить", + "To restore this document, restore the workspace first.": "Чтобы восстановить этот документ, сначала восстановите рабочую область.", + "Trash is empty.": "Корзина пуста.", + "Unpin Document": "Открепить документ", + "Workspace not found": "Рабочее пространство не найдено", + "You are on your personal site. You also have access to the following sites:": "Вы находитесь на своем личном сайте. У вас также есть доступ к следующим сайтам:", + "You may delete a workspace forever once it has no documents in it.": "Вы можете навсегда удалить рабочую область, если в ней нет документов.", + "Trash": "Корзина", + "Document will be moved to Trash.": "Документ будет перемещен в Корзину." + }, + "DocTour": { + "Cannot construct a document tour from the data in this document. Ensure there is a table named GristDocTour with columns Title, Body, Placement, and Location.": "Не удается создать тур по документу на основе данных в этом документе. Убедитесь, что существует таблица с именем GristDocTour со столбцами Title, Body, Placement и Location.", + "No valid document tour": "Нет действительного тура по документу" + }, + "DocumentSettings": { + "Document Settings": "Настройки документа", + "Currency:": "Валюта:", + "Ok": "Ok", + "Locale:": "Регион:", + "Save and Reload": "Сохранить и Перезагрузить", + "Save": "Сохранить", + "Time Zone:": "Часовой пояс:", + "API": "API", + "Engine (experimental {{span}} change at own risk):": "Engine (экспериментальный {{span}} менять на свой страх и риск):", + "Local currency ({{currency}})": "Местная валюта ({{currency}})", + "This document's ID (for API use):": "Идентификатор этого документа (для использования API):", + "Document ID copied to clipboard": "Идентификатор документа скопирован в буфер обмена" + }, + "DocPageModel": { + "Add Widget to Page": "Добавить виджет на страницу", + "You do not have edit access to this document": "У вас нет доступа к редактированию этого документа", + "Add Empty Table": "Добавить пустую таблицу", + "Reload": "Перезагрузить", + "Add Page": "Добавить страницу", + "Document owners can attempt to recover the document. [{{error}}]": "Владельцы документов могут попытаться восстановить документ. [{{error}}]", + "Enter recovery mode": "Войти в режим восстановления", + "Error accessing document": "Ошибка доступа к документу", + "Sorry, access to this document has been denied. [{{error}}]": "Извините, в доступе к этому документу было отказано. [{{error}}]", + "You can try reloading the document, or using recovery mode. Recovery mode opens the document to be fully accessible to owners, and inaccessible to others. It also disables formulas. [{{error}}]": "Вы можете попробовать перезагрузить документ или использовать режим восстановления. Режим восстановления открывает документ, чтобы он был полностью доступен для владельцев и недоступен для других. Это также отключает формулы. [{{error}}]" + }, + "DocumentUsage": { + "Data Size": "Размер данных", + "Attachments Size": "Размер вложений", + "For higher limits, ": "Для более высоких пределов, ", + "Rows": "Строки", + "Contact the site owner to upgrade the plan to raise limits.": "Свяжитесь с владельцем сайта для обновления тарифа и увеличения лимитов.", + "Usage": "Использование", + "Usage statistics are only available to users with full access to the document data.": "Статистика использования доступна только пользователям, имеющим полный доступ к данным документа.", + "start your 30-day free trial of the Pro plan.": "начните свою 30-дневную бесплатную пробную версию тарифа Pro." + }, + "Drafts": { + "Restore last edit": "Восстановить последнее редактирование", + "Undo discard": "Отменить сброс" + }, + "DuplicateTable": { + "Copy all data in addition to the table structure.": "Скопируйте все данные в дополнение к структуре таблицы.", + "Instead of duplicating tables, it's usually better to segment data using linked views. {{link}}": "Вместо дублирования таблиц обычно лучше сегментировать данные, используя связанные представления. {{link}}", + "Name for new table": "Имя для новой таблицы", + "Only the document default access rules will apply to the copy.": "К копии будут применяться только правила доступа к документу по умолчанию." + }, + "ExampleInfo": { + "Check out our related tutorial for how to model business data, use formulas, and manage complexity.": "Ознакомьтесь с нашим соответствующим учебником, чтобы узнать, как моделировать бизнес-данные, использовать формулы и управлять сложными представлениями данных.", + "Investment Research": "Инвестиционные исследования", + "Check out our related tutorial for how to link data, and create high-productivity layouts.": "Ознакомьтесь с нашим соответствующим учебником, чтобы узнать, как связывать данные и создавать высокопроизводительные макеты.", + "Lightweight CRM": "Легкая CRM", + "Tutorial: Analyze & Visualize": "Учебник: Анализ и визуализация", + "Check out our related tutorial to learn how to create summary tables and charts, and to link charts dynamically.": "Ознакомьтесь с нашим соответствующим учебником, чтобы узнать, как создавать сводные таблицы и графики, а также динамически связывать графики.", + "Tutorial: Create a CRM": "Учебник: Создание CRM", + "Tutorial: Manage Business Data": "Учебник: Управление бизнес-данными", + "Welcome to the Investment Research template": "Добро пожаловать в шаблон \"Инвестиционные исследования\"", + "Welcome to the Afterschool Program template": "Добро пожаловать в шаблон \"Внеклассная работа\"", + "Welcome to the Lightweight CRM template": "Добро пожаловать в шаблон \"Легкая CRM\"", + "Afterschool Program": "Внеклассная работа" + }, + "FieldMenus": { + "Save as common settings": "Сохранить как общие настройки", + "Using separate settings": "Использование раздельных настроек", + "Revert to common settings": "Возврат к общим настройкам", + "Using common settings": "Использование общих настроек", + "Use separate settings": "Использовать раздельные настройки" + }, + "GridOptions": { + "Grid Options": "Параметры сетки", + "Vertical Gridlines": "Вертикальные линии сетки", + "Horizontal Gridlines": "Горизонтальные линии сетки", + "Zebra Stripes": "Полосы зебры" + }, + "HomeIntro": { + "Interested in using Grist outside of your team? Visit your free ": "Заинтересованы в использовании Grist вне вашей команды? Попробуйте бесплатно ", + "Any documents created in this site will appear here.": "Любые документы, созданные на этом сайте, появятся здесь.", + "Browse Templates": "Просмотр шаблонов", + "Create Empty Document": "Создать пустой документ", + "Import Document": "Импорт документа", + "Get started by creating your first Grist document.": "Начните с создания вашего первого документа Grist.", + "Get started by exploring templates, or creating your first Grist document.": "Начните с изучения шаблонов или создания своего первого документа Grist.", + "Invite Team Members": "Пригласить членов команды", + "Get started by inviting your team and creating your first Grist document.": "Начните с приглашения своей команды и создания вашего первого документа Grist.", + "Help Center": "Справочный центр", + "Welcome to Grist, {{name}}!": "Добро пожаловать в Grist, {{name}}!", + "Sign up": "Регистрация", + "Sprouts Program": "Программа Внедрения", + "This workspace is empty.": "Эта рабочая область пуста.", + "Visit our {{link}} to learn more.": "Посетите наш {{link}} чтобы узнать больше.", + "Welcome to Grist!": "Добро пожаловать в Grist!", + "Welcome to {{orgName}}": "Добро пожаловать в {{orgName}}", + "personal site": "личный сайт", + "You have read-only access to this site. Currently there are no documents.": "Вы имеете доступ к этому сайту только для просмотра. В настоящее время документов нет." + }, + "HomeLeftPane": { + "Import Document": "Импорт документа", + "All Documents": "Все документы", + "Manage Users": "Управление пользователями", + "Create Workspace": "Создать рабочее пространство", + "Access Details": "Детали доступа", + "Create Empty Document": "Создать пустой документ", + "Delete": "Удалить", + "Examples & Templates": "Примеры & Шаблоны", + "Rename": "Переименовать", + "Delete {{workspace}} and all included documents?": "Удалить {{workspace}} и все прилагаемые документы?", + "Trash": "Корзина", + "Workspaces": "Рабочие пространства", + "Workspace will be moved to Trash.": "Рабочее пространство будет перемещено в корзину." + }, + "GridViewMenus": { + "Add to sort": "Добавить в сортировку", + "Column Options": "Параметры столбца", + "Add Column": "Добавить столбец", + "Clear values": "Очистить значения", + "Delete {{count}} columns_one": "Удалить столбец", + "Filter Data": "Фильтровать данные", + "Convert formula to data": "Преобразование формулы в данные", + "Freeze {{count}} columns_one": "Закрепить этот столбец", + "Freeze {{count}} columns_other": "Закрепить {{count}} столбцы", + "Freeze {{count}} more columns_one": "Закрепить еще одну колонку", + "Delete {{count}} columns_other": "Удалить {{count}} столбцы", + "Hide {{count}} columns_one": "Скрыть столбец", + "Freeze {{count}} more columns_other": "Закрепить ещё {{count}} столбцов", + "Insert column to the {{to}}": "Вставьте столбец в {{to}}", + "More sort options ...": "Больше параметров сортировки…", + "Hide {{count}} columns_other": "Скрыть {{count}} столбцы", + "Rename column": "Переименовать столбец", + "Reset {{count}} entire columns_one": "Сбросить весь столбец целиком", + "Reset {{count}} columns_other": "Сбросить {{count}} столбцов", + "Reset {{count}} columns_one": "Сброс столбца", + "Sorted (#{{count}})_one": "Отсортировано (#{{count}})", + "Reset {{count}} entire columns_other": "Сбросить {{count}} столбцов целиком", + "Sorted (#{{count}})_other": "Отсортировано (#{{count}})", + "Unfreeze all columns": "Открепить все столбцы", + "Show column {{- label}}": "Показать столбец {{- label}}", + "Sort": "Сортировать", + "Unfreeze {{count}} columns_other": "Открепить {{count}} столбцов", + "Unfreeze {{count}} columns_one": "Открепить этот столбец" + }, + "FilterBar": { + "SearchColumns": "Столбцы поиска", + "Search Columns": "Столбцы поиска" + }, + "FilterConfig": { + "Add Column": "Добавить столбец" + }, + "GristDoc": { + "Import from file": "Импорт из файла", + "Added new linked section to view {{viewName}}": "Добавлен новый связанный раздел в представление {{viewName}}", + "Saved linked section {{title}} in view {{name}}": "Сохраненный связанный раздел {{title}} в представлении {{name}}" + }, + "Importer": { + "Merge rows that match these fields:": "Объедините строки, соответствующие этим полям:", + "Select fields to match on": "Выберите поля для сопоставления", + "Update existing records": "Обновите существующие записи" + }, + "LeftPanelCommon": { + "Help Center": "Справочный центр" + }, + "RowContextMenu": { + "Duplicate rows_other": "Дублировать строки", + "Duplicate rows_one": "Дублировать строку", + "Copy anchor link": "Скопировать якорную ссылку", + "Insert row below": "Вставить строку ниже", + "Insert row": "Вставить строку", + "Insert row above": "Вставить строку выше", + "Delete": "Удалить" + }, + "RecordLayout": { + "Updating record layout.": "Обновление макета записи." + }, + "NotifyUI": { + "Cannot find personal site, sorry!": "Не могу найти личный сайт, извините!", + "Report a problem": "Сообщить о проблеме", + "Give feedback": "Дайте отзыв", + "Ask for help": "Попросить помощи", + "No notifications": "Нет уведомлений", + "Notifications": "Уведомления", + "Renew": "Продлить", + "Go to your free personal site": "Перейдите на свой бесплатный личный сайт", + "Upgrade Plan": "Обновить тариф" + }, + "OpenVideoTour": { + "Grist Video Tour": "Видео-тур по Grist", + "YouTube video player": "Видеоплеер YouTube", + "Video Tour": "Видео-тур" + }, + "OnBoardingPopups": { + "Finish": "Закончить", + "Next": "Дальше" + }, + "PageWidgetPicker": { + "Group by": "Группировать по", + "Building {{- label}} widget": "Создание {{- label}} виджета", + "Add to Page": "Добавить на страницу", + "Select Data": "Выбор данных", + "Select Widget": "Выбор виджета" + }, + "RightPanel": { + "SOURCE DATA": "ИСТОЧНИК ДАННЫХ", + "Theme": "Тема", + "Data": "Данные", + "Fields_other": "Поля", + "Detach": "Отсоединить", + "GROUPED BY": "СГРУППИРОВАННЫЕ ПО", + "CHART TYPE": "ТИП ДИАГРАММЫ", + "COLUMN TYPE": "ТИП СТОЛБЦА", + "Columns_one": "Столбец", + "Change Widget": "Изменить виджет", + "CUSTOM": "ПЕРСОНАЛЬНО", + "DATA TABLE": "ТАБЛИЦА ДАННЫХ", + "Fields_one": "Поле", + "Columns_other": "Столбцы", + "DATA TABLE NAME": "НАЗВАНИЕ ТАБЛИЦЫ ДАННЫХ", + "Edit Data Selection": "Редактировать выборку данных", + "Row Style": "Стиль строки", + "ROW STYLE": "СТИЛЬ СТРОКИ", + "SELECT BY": "ВЫБОР ПО", + "Series_other": "Ряды", + "SELECTOR FOR": "СЕЛЕКТОР ДЛЯ", + "Save": "Сохранить", + "Select Widget": "Выберите виджет", + "Series_one": "Ряд", + "Sort & Filter": "Сортировка & Фильтрация", + "TRANSFORM": "ПРЕОБРАЗОВАНИЕ", + "WIDGET TITLE": "ЗАГОЛОВОК ВИДЖЕТА", + "You do not have edit access to this document": "У вас нет прав на редактирование этого документа", + "Widget": "Виджет" + }, + "PermissionsWidget": { + "Allow All": "Разрешить все", + "Deny All": "Запретить все", + "Read Only": "Только чтение" + }, + "Pages": { + "Delete": "Удалить", + "Delete data and this page.": "Удалить данные и эту страницу.", + "The following tables will no longer be visible_other": "Следующие таблицы больше не будут видны", + "The following tables will no longer be visible_one": "Следующая таблица больше не будет видна" + }, + "RecordLayoutEditor": { + "Save Layout": "Сохранить макет", + "Add Field": "Добавить поле", + "Cancel": "Отмена", + "Create New Field": "Создать новое поле", + "Show field {{- label}}": "Показать поле {{- label}}" + }, + "RefSelect": { + "No columns to add": "Нет столбцов для добавления", + "Add Column": "Добавить столбец" + }, + "PluginScreen": { + "Import failed: ": "Сбой импорта: " + }, + "SelectionSummary": { + "Copied to clipboard": "Скопировано в буфер обмена" + }, + "SiteSwitcher": { + "Create new team site": "Создать новый сайт группы", + "Switch Sites": "Переключить сайты" + }, + "TopBar": { + "Manage Team": "Управление командой" + }, + "TriggerFormulas": { + "Any field": "Любое поле", + "Apply on changes to:": "Вычислять при изменениях в:", + "Current field ": "Текущее поле ", + "Apply on record changes": "Вычислять при изменениях записи", + "Apply to new records": "Вычислять при создании записей", + "Cancel": "Отмена", + "OK": "OK", + "Close": "Закрыть" + }, + "ThemeConfig": { + "Appearance ": "Оформление ", + "Switch appearance automatically to match system": "Автоматическое переключение оформления в соответствии с системной настройкой" + }, + "UserManagerModel": { + "In Full": "Полный", + "None": "Без доступа", + "View & Edit": "Просмотр & Редактирование", + "Viewer": "Наблюдатель", + "Owner": "Владелец", + "No Default Access": "Нет доступа по умолчанию", + "Editor": "Редактор", + "View Only": "Только просмотр" + }, + "ViewAsBanner": { + "UnknownUser": "Неизвестный пользователь" + }, + "ViewConfigTab": { + "Advanced settings": "Расширенные настройки", + "Make On-Demand": "Преобразовать в Хранилище", + "Unmark On-Demand": "Убрать Хранилище", + "Big tables may be marked as \"on-demand\" to avoid loading them into the data engine.": "Большие таблицы могут быть помечены как \"Хранилище\", чтобы избежать перегрузки сервера при вычислениях." + }, + "ViewLayoutMenu": { + "Advanced Sort & Filter": "Расширенная Сортировка & Фильтр", + "Delete record": "Удалить запись", + "Delete widget": "Удалить виджет", + "Download as XLSX": "Скачать как XLSX", + "Download as CSV": "Скачать как CSV" + }, + "FieldEditor": { + "It should be impossible to save a plain data value into a formula column": "Должно быть невозможно сохранить значение простых данных в столбце формулы" } } From 5a324f135874783908551805715c21725009ea91 Mon Sep 17 00:00:00 2001 From: jarek Date: Sat, 4 Feb 2023 00:56:24 +0100 Subject: [PATCH 14/14] Adding new flags for supported locales (#420) * Adding new flags for supported locales * Removing pl-PL locale code from tests * Linting --- app/client/lib/localization.ts | 8 +++++++- app/common/Locales.ts | 7 ++++++- static/icons/locales/PL.svg | 15 +++++++++++++++ static/icons/locales/RU.svg | 16 ++++++++++++++++ static/icons/locales/UA.svg | 14 ++++++++++++++ test/nbrowser/Localization.ts | 24 ++++++++++++------------ 6 files changed, 70 insertions(+), 14 deletions(-) create mode 100644 static/icons/locales/PL.svg create mode 100644 static/icons/locales/RU.svg create mode 100644 static/icons/locales/UA.svg diff --git a/app/client/lib/localization.ts b/app/client/lib/localization.ts index 39094809..39d69541 100644 --- a/app/client/lib/localization.ts +++ b/app/client/lib/localization.ts @@ -40,7 +40,13 @@ export async function setupLocale() { const resourceUrl = loadPath.replace('{{lng}}', lang.replace("-", "_")).replace('{{ns}}', n); const response = await fetch(resourceUrl); if (!response.ok) { - throw new Error(`Failed to load ${resourceUrl}`); + // Throw only if we don't have any fallbacks. + if (lang === i18next.options.fallbackLng && n === i18next.options.defaultNS) { + throw new Error(`Failed to load ${resourceUrl}`); + } else { + console.warn(`Failed to load ${resourceUrl}`); + return; + } } i18next.addResourceBundle(lang, n, await response.json()); } diff --git a/app/common/Locales.ts b/app/common/Locales.ts index b9a5d52a..045c51f6 100644 --- a/app/common/Locales.ts +++ b/app/common/Locales.ts @@ -75,7 +75,12 @@ export function getCountryCode(locale: string) { if (locale === 'en') { return 'US'; } let countryCode = locale.split(/[-_]/)[1]; if (countryCode) { return countryCode.toUpperCase(); } - countryCode = locale.toUpperCase(); + + // Some defaults that we support and can't be read from language code. + countryCode = { + 'uk': 'UA', // Ukraine + }[locale] ?? locale.toUpperCase(); + // Test if we can use language as a country code. if (localeCodes.map(code => code.split(/[-_]/)[1]).includes(countryCode)) { return countryCode; diff --git a/static/icons/locales/PL.svg b/static/icons/locales/PL.svg new file mode 100644 index 00000000..57f279d1 --- /dev/null +++ b/static/icons/locales/PL.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/static/icons/locales/RU.svg b/static/icons/locales/RU.svg new file mode 100644 index 00000000..4404aec4 --- /dev/null +++ b/static/icons/locales/RU.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/static/icons/locales/UA.svg b/static/icons/locales/UA.svg new file mode 100644 index 00000000..8e5737ce --- /dev/null +++ b/static/icons/locales/UA.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/test/nbrowser/Localization.ts b/test/nbrowser/Localization.ts index 6b66be15..4ae6fd45 100644 --- a/test/nbrowser/Localization.ts +++ b/test/nbrowser/Localization.ts @@ -51,8 +51,8 @@ describe("Localization", function() { assert.deepEqual(gristConfig.namespaces.sort(), [...namespaces].sort()); }); - // Now make a Polish language file, and test that it is used. - describe("with Polish language file", function() { + // Now make a uz-UZ language file, and test that it is used. + describe("with uz-UZ language file", function() { let oldEnv: testUtils.EnvironmentSnapshot; let tempLocale: string; let existingLocales: string[]; @@ -65,7 +65,7 @@ describe("Localization", function() { oldEnv = new testUtils.EnvironmentSnapshot(); // Add another language to the list of supported languages. tempLocale = makeCopy(); - createLanguage(tempLocale, "pl"); + createLanguage(tempLocale, "uz"); process.env.GRIST_LOCALES_DIR = tempLocale; await server.restart(); }); @@ -79,7 +79,7 @@ describe("Localization", function() { const homeUrl = `${server.getHost()}/o/docs`; // Read response from server, and check that it contains the correct language. const enResponse = await (await fetch(homeUrl)).text(); - const plResponse = await (await fetch(homeUrl, {headers: {"Accept-Language": "pl-PL,pl;q=1"}})).text(); + const uzResponse = await (await fetch(homeUrl, {headers: {"Accept-Language": "uz-UZ,uz;q=1"}})).text(); const ptResponse = await (await fetch(homeUrl, {headers: {"Accept-Language": "pt-PR,pt;q=1"}})).text(); function present(response: string, ...langs: string[]) { @@ -96,19 +96,19 @@ describe("Localization", function() { // English locale is preloaded always. present(enResponse, "en"); - present(plResponse, "en"); + present(uzResponse, "en"); present(ptResponse, "en"); // Other locales are not preloaded for English. - notPresent(enResponse, "pl", "pl-PL", "en-US"); + notPresent(enResponse, "uz", "un-UZ", "en-US"); - // For Polish we have additional pl locale. - present(plResponse, "pl"); - // But only pl code is preloaded. - notPresent(plResponse, "pl-PL"); + // For uz-UZ we have additional uz locale. + present(uzResponse, "uz"); + // But only uz code is preloaded. + notPresent(uzResponse, "uz-UZ"); // For Portuguese we have only en. - notPresent(ptResponse, "pt", "pt-PR", "pl", "en-US"); + notPresent(ptResponse, "pt", "pt-PR", "uz", "en-US"); }); it("loads correct languages from file system", async function() { @@ -116,7 +116,7 @@ describe("Localization", function() { await driver.navigate().refresh(); assert.equal(await driver.findWait('.test-welcome-title', 3000).getText(), 'TestMessage'); const gristConfig: any = await driver.executeScript("return window.gristConfig"); - assert.sameDeepMembers(gristConfig.supportedLngs, [...existingLocales, 'pl']); + assert.sameDeepMembers(gristConfig.supportedLngs, [...existingLocales, 'uz']); }); });