Merge branch 'release/v2.6.0' into bugfix/Bug69117

This commit is contained in:
Viktor Fomin 2024-07-22 14:56:24 +03:00
commit 02ef246e83
161 changed files with 1684 additions and 2629 deletions

View File

@ -29,14 +29,14 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using Frontend.Tests;
using Frontend.Tests.Models;
using System.Text.RegularExpressions;
using Frontend.Tests;
using Frontend.Tests.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
@ -47,7 +47,7 @@ using WeCantSpell.Hunspell;
namespace Frontend.Tests;
public class LocalesTest
{
{
public static string BasePath
{
get
@ -56,18 +56,18 @@ public class LocalesTest
}
}
public static bool Save
{
get
{
bool save;
if (bool.TryParse(Environment.GetEnvironmentVariable("SAVE"), out save))
{
return save;
}
return false;
}
public static bool Save
{
get
{
bool save;
if (bool.TryParse(Environment.GetEnvironmentVariable("SAVE"), out save))
{
return save;
}
return false;
}
}
public List<string> Workspaces { get; set; }
@ -77,13 +77,14 @@ public class LocalesTest
public List<KeyValuePair<string, string>> NotTranslatedToasts { get; set; }
public List<KeyValuePair<string, string>> NotTranslatedProps { get; set; }
public List<LanguageItem> CommonTranslations { get; set; }
public List<ParseJsonError> ParseJsonErrors { get; set; }
public static string ConvertPathToOS { get; private set; }
public List<string> ForbiddenElements { get { return new List<string>() { "ONLYOFFICE", "DOCSPACE" }; } }
//public List<JsonEncodingError> WrongEncodingJsonErrors { get; set; }
public List<ParseJsonError> ParseJsonErrors { get; set; }
public static string ConvertPathToOS { get; private set; }
public List<string> ForbiddenElements { get { return new List<string>() { "ONLYOFFICE", "DOCSPACE" }; } }
public List<string> SkipForbiddenKeys = new List<string> { "OrganizationName", "ProductName", "ProductEditorsName" };
//public List<JsonEncodingError> WrongEncodingJsonErrors { get; set; }
private static readonly string _md5ExcludesPath = Path.GetFullPath(Utils.ConvertPathToOS("../../../md5-excludes.json"));
private static readonly string _spellCheckCommonExcludesPath = Path.GetFullPath(Utils.ConvertPathToOS("../../../spellcheck-excludes-common.json"));
private static readonly string _spellCheckExcludesPath = Path.GetFullPath(Utils.ConvertPathToOS("../../../spellcheck-excludes.json"));
@ -104,7 +105,7 @@ public class LocalesTest
[OneTimeSetUp]
public void Setup()
{
{
ParseJsonErrors = new List<ParseJsonError>();
//WrongEncodingJsonErrors = new List<JsonEncodingError>();
@ -357,14 +358,14 @@ public class LocalesTest
TestContext.Progress.WriteLine($"Found CommonTranslations = {CommonTranslations.Count()}. First path is '{CommonTranslations.FirstOrDefault()?.Path}'");
TestContext.Progress.WriteLine($"Found Md5Excludes = {Md5Excludes.Count} Path to file '{_md5ExcludesPath}'");
TestContext.Progress.WriteLine($"Found SpellCheckCommonExcludes = {SpellCheckCommonExcludes.Count} Path to file '{_spellCheckCommonExcludesPath}'");
TestContext.Progress.WriteLine($"Save spell check excludes = {Save} Path to file '{_spellCheckExcludesPath}'");
}
TestContext.Progress.WriteLine($"Found Md5Excludes = {Md5Excludes.Count} Path to file '{_md5ExcludesPath}'");
TestContext.Progress.WriteLine($"Found SpellCheckCommonExcludes = {SpellCheckCommonExcludes.Count} Path to file '{_spellCheckCommonExcludesPath}'");
TestContext.Progress.WriteLine($"Save spell check excludes = {Save} Path to file '{_spellCheckExcludesPath}'");
}
[Test, Order(1)]
[Category("Locales")]
public void LanguageTranslatedPercentTest()
@ -499,7 +500,7 @@ public class LocalesTest
.ToList();
Assert.AreEqual(0, duplicates.Count, string.Join(", ", duplicates.Select(d => JObject.FromObject(d).ToString())));
}
}
[Test, Order(6)]
[Category("Locales")]
@ -514,10 +515,10 @@ public class LocalesTest
.Where(f => !f.Path.Contains("Banner.js")) // skip Banner.js (translations from firebase)
.SelectMany(j => j.TranslationKeys)
.Select(k => k.Substring(k.IndexOf(":") + 1))
.Distinct();
//var foo = JavaScriptFiles
// .Where(f => !f.Path.Contains("Banner.js"))
.Distinct();
//var foo = JavaScriptFiles
// .Where(f => !f.Path.Contains("Banner.js"))
// .Where(t => t.TranslationKeys.Any(k => k == "foo")).FirstOrDefault();
var notFoundJsKeys = allJsTranslationKeys.Except(allEnKeys);
@ -525,8 +526,8 @@ public class LocalesTest
Assert.AreEqual(0, notFoundJsKeys.Count(),
"Some i18n-keys are not exist in translations in 'en' language: Keys:\r\n{0}",
string.Join("\r\n", notFoundJsKeys));
}
}
[Test, Order(7)]
[Category("Locales")]
public void DublicatesFilesByMD5HashTest()
@ -541,8 +542,8 @@ public class LocalesTest
.ToList();
Assert.AreEqual(0, duplicatesByMD5.Count, "Dublicates by MD5 hash:\r\n" + string.Join("\r\n", duplicatesByMD5.Select(d => $"\r\nMD5='{d.Key}':\r\n{string.Join("\r\n", d.Paths.Select(p => p))}'")));
}
}
[Test, Order(8)]
[Category("Locales")]
public void UselessTranslationKeysTest()
@ -627,8 +628,8 @@ public class LocalesTest
{
Language = g.Key,
TranslationsWithVariables = g.ToList()
.SelectMany(t => t.Translations.Select(k => new TranslationItem($"{t.FileName}:{k.Key}", k.Value)))
//.Where(k => k.Value.IndexOf("{{") != -1)
.SelectMany(t => t.Translations.Select(k => new TranslationItem($"{t.FileName}:{k.Key}", k.Value)))
//.Where(k => k.Value.IndexOf("{{") != -1)
.Select(t => new
{
t.Key,
@ -654,12 +655,12 @@ public class LocalesTest
var i = 0;
var errorsCount = 0;
foreach (var enKeyWithVariables in enWithVariables)
{
foreach (var lng in otherLanguagesWithVariables)
{
var lngKey = lng.TranslationsWithVariables
.Where(t => t.Key == enKeyWithVariables.Key)
foreach (var enKeyWithVariables in enWithVariables)
{
foreach (var lng in otherLanguagesWithVariables)
{
var lngKey = lng.TranslationsWithVariables
.Where(t => t.Key == enKeyWithVariables.Key)
.FirstOrDefault();
if (lngKey == null)
@ -671,8 +672,8 @@ public class LocalesTest
}
if (enKeyWithVariables.Variables.Count != lngKey.Variables.Count)
{
// wrong
{
// wrong
message += $"{++i}. lng='{lng.Language}' key='{lngKey.Key}' has less variables then 'en' language have " +
$"(en={enKeyWithVariables.Variables.Count}|{lng.Language}={lngKey.Variables.Count})\r\n" +
$"'en': '{enKeyWithVariables.Value}'\r\n'{lng.Language}': '{lngKey.Value}'\r\n\r\n";
@ -680,10 +681,10 @@ public class LocalesTest
}
if (!lngKey.Variables.All(v => enKeyWithVariables.Variables.Contains(v)))
{
// wrong
message += $"{++i}. lng='{lng.Language}' key='{lngKey.Key}' has not equals variables of 'en' language have \r\n" +
$"'{enKeyWithVariables.Value}' Variables=[{string.Join(",", enKeyWithVariables.Variables)}]\r\n" +
{
// wrong
message += $"{++i}. lng='{lng.Language}' key='{lngKey.Key}' has not equals variables of 'en' language have \r\n" +
$"'{enKeyWithVariables.Value}' Variables=[{string.Join(",", enKeyWithVariables.Variables)}]\r\n" +
$"'{lngKey.Value}' Variables=[{string.Join(",", lngKey.Variables)}]\r\n\r\n";
errorsCount++;
}
@ -708,8 +709,8 @@ public class LocalesTest
{
Language = g.Key,
TranslationsWithTags = g.ToList()
.SelectMany(t => t.Translations)
//.Where(k => k.Value.IndexOf("<") != -1)
.SelectMany(t => t.Translations)
//.Where(k => k.Value.IndexOf("<") != -1)
.Select(t => new
{
t.Key,
@ -735,22 +736,22 @@ public class LocalesTest
var i = 0;
var errorsCount = 0;
foreach (var enKeyWithTags in enWithTags)
{
foreach (var lng in otherLanguagesWithTags)
{
var lngKey = lng.TranslationsWithTags
.Where(t => t.Key == enKeyWithTags.Key)
.FirstOrDefault();
if (lngKey == null)
{
foreach (var enKeyWithTags in enWithTags)
{
foreach (var lng in otherLanguagesWithTags)
{
var lngKey = lng.TranslationsWithTags
.Where(t => t.Key == enKeyWithTags.Key)
.FirstOrDefault();
if (lngKey == null)
{
// wrong
//message += $"{++i}. lng='{lng.Language}' key='{enKeyWithTags.Key}' not found\r\n\r\n";
//errorsCount++;
continue;
}
continue;
}
if (enKeyWithTags.Tags.Count != lngKey.Tags.Count)
{
// wrong
@ -758,8 +759,8 @@ public class LocalesTest
$"(en={enKeyWithTags.Tags.Count}|{lng.Language}={lngKey.Tags.Count})\r\n" +
$"'en': '{enKeyWithTags.Value}'\r\n'{lng.Language}': '{lngKey.Value}'\r\n\r\n";
errorsCount++;
}
}
if (!lngKey.Tags.All(v => enKeyWithTags.Tags.Contains(v)))
{
// wrong
@ -767,9 +768,9 @@ public class LocalesTest
$"'{enKeyWithTags.Value}' Tags=[{string.Join(",", enKeyWithTags.Tags)}]\r\n" +
$"'{lngKey.Value}' Tags=[{string.Join(",", lngKey.Tags)}]\r\n\r\n";
errorsCount++;
}
}
}
}
}
/*foreach (var lng in otherLanguagesWithTags)
@ -809,19 +810,18 @@ public class LocalesTest
}*/
Assert.AreEqual(0, errorsCount, message);
}
}
[Test, Order(13)]
[Category("Locales")]
public void ForbiddenValueElementsTest()
{
var message = $"Next keys have forbidden values `{string.Join(",", ForbiddenElements)}`:\r\n\r\n";
var message = $"Next keys have forbidden values `{string.Join(",", ForbiddenElements)}`:\r\n\r\n";
var exists = false;
var i = 0;
var i = 0;
foreach (var module in ModuleFolders)
{
if (module.AvailableLanguages == null)
@ -844,38 +844,41 @@ public class LocalesTest
message += string.Join("\r\n", keys) + "\r\n\r\n";
}
}
}
foreach (var lng in CommonTranslations)
{
var translationItems = lng.Translations.Where(f => ForbiddenElements.Any(elem => f.Value.ToUpper().Contains(elem))).ToList();
if (!translationItems.Any())
continue;
exists = true;
message += $"{++i}. Language '{lng.Language}' (Count: {translationItems.Count}). Path '{lng.Path}' " +
$"Keys:\r\n\r\n";
var keys = translationItems.Select(t => t.Key).ToList();
var translationItems = lng.Translations
.Where(elem => !SkipForbiddenKeys.Exists(k => k == elem.Key))
.Where(f => ForbiddenElements.Any(elem => f.Value.ToUpper().Contains(elem)))
.ToList();
if (!translationItems.Any())
continue;
exists = true;
message += $"{++i}. Language '{lng.Language}' (Count: {translationItems.Count}). Path '{lng.Path}' " +
$"Keys:\r\n\r\n";
var keys = translationItems.Select(t => t.Key).ToList();
message += string.Join("\r\n", keys) + "\r\n\r\n";
}
Assert.AreEqual(false, exists, message);
}
}
[Test, Order(14)]
[Category("Locales")]
[Category("Locales")]
public void ForbiddenKeysElementsTest()
{
var message = $"Next keys have forbidden elements in names `{string.Join(",", ForbiddenElements)}`:\r\n\r\n";
var message = $"Next keys have forbidden elements in names `{string.Join(",", ForbiddenElements)}`:\r\n\r\n";
var exists = false;
var i = 0;
var i = 0;
foreach (var module in ModuleFolders)
{
if (module.AvailableLanguages == null)
@ -883,9 +886,8 @@ public class LocalesTest
foreach (var lng in module.AvailableLanguages)
{
var translationItems = lng.Translations.Where(f => ForbiddenElements.Any(elem => f.Key.ToUpper().Contains(elem))).ToList();
var translationItems = lng.Translations.Where(f => ForbiddenElements.Any(elem => f.Key.ToUpper().Contains(elem))).ToList();
if (!translationItems.Any())
continue;
@ -899,28 +901,31 @@ public class LocalesTest
message += string.Join("\r\n", keys) + "\r\n\r\n";
}
}
}
foreach (var lng in CommonTranslations)
{
var translationItems = lng.Translations.Where(f => ForbiddenElements.Any(elem => f.Key.ToUpper().Contains(elem))).ToList();
if (!translationItems.Any())
continue;
exists = true;
message += $"{++i}. Language '{lng.Language}' (Count: {translationItems.Count}). Path '{lng.Path}' " +
$"Keys:\r\n\r\n";
var keys = translationItems.Select(t => t.Key).ToList();
{
var translationItems = lng.Translations
.Where(elem => !SkipForbiddenKeys.Exists(k => k == elem.Key))
.Where(f => ForbiddenElements.Any(elem => f.Key.ToUpper().Contains(elem)))
.ToList();
if (!translationItems.Any())
continue;
exists = true;
message += $"{++i}. Language '{lng.Language}' (Count: {translationItems.Count}). Path '{lng.Path}' " +
$"Keys:\r\n\r\n";
var keys = translationItems.Select(t => t.Key).ToList();
message += string.Join("\r\n", keys) + "\r\n\r\n";
}
Assert.AreEqual(false, exists, message);
}
}
[Test, Order(15)]
[Category("Locales")]
public void EmptyValueKeysTest()
@ -1023,8 +1028,8 @@ public class LocalesTest
}
Assert.AreEqual(false, exists, message);
}
}
[Test, Order(16)]
[Category("Locales")]
public void NotTranslatedKeysTest()
@ -1070,8 +1075,8 @@ public class LocalesTest
}
Assert.AreEqual(false, exists, message);
}
}
[Test, Order(17)]
[Category("Locales")]
public void NotTranslatedCommonKeysTest()
@ -1113,7 +1118,7 @@ public class LocalesTest
[Test, Order(18)]
[Category("Locales")]
public void NotAllLanguageTranslatedTest()
{
{
var groupedByLng = TranslationFiles
.GroupBy(t => t.Language)
.Select(grp => new { Lng = grp.Key, Count = grp.Count(), Files = grp.ToList() })
@ -1165,8 +1170,8 @@ public class LocalesTest
}
Assert.AreEqual(0, incompleteList.Count, message);
}
}
[Test, Order(19)]
[Category("SpellCheck")]
public void SpellCheckTest()
@ -1207,43 +1212,43 @@ public class LocalesTest
if (result.HasProblems)
{
var incorrectWords = result.SpellIssues
.Where(t => !SpellCheckCommonExcludes
.Exists(e => e.Equals(t.Word, StringComparison.InvariantCultureIgnoreCase)))
.Select(issue => $"'{issue.Word}' " +
var incorrectWords = result.SpellIssues
.Where(t => !SpellCheckCommonExcludes
.Exists(e => e.Equals(t.Word, StringComparison.InvariantCultureIgnoreCase)))
.Select(issue => $"'{issue.Word}' " +
$"Suggestion: '{issue.Suggestions.FirstOrDefault()}'")
.ToList();
if (!incorrectWords.Any())
continue;
message += $"{++i}. lng='{group.Language}' file='{g.FilePath}'\r\nkey='{item.Key}' " +
$"value='{item.Value}'\r\nIncorrect words:\r\n" +
message += $"{++i}. lng='{group.Language}' file='{g.FilePath}'\r\nkey='{item.Key}' " +
$"value='{item.Value}'\r\nIncorrect words:\r\n" +
$"{string.Join("\r\n", incorrectWords)}\r\n\r\n";
errorsCount++;
if (Save)
{
if (Save)
{
foreach (var word in result.SpellIssues
.Where(issue => issue.Suggestions.Any())
.Select(issue => issue.Word))
{
if (!spellCheckExclude.Excludes.Contains(word))
{
spellCheckExclude.Excludes.Add(word);
}
}
.Select(issue => issue.Word))
{
if (!spellCheckExclude.Excludes.Contains(word))
{
spellCheckExclude.Excludes.Add(word);
}
}
}
}
}
}
}
if (Save)
{
spellCheckExclude.Excludes.Sort();
list.Add(spellCheckExclude);
if (Save)
{
spellCheckExclude.Excludes.Sort();
list.Add(spellCheckExclude);
}
}
catch (NotSupportedException)
@ -1253,135 +1258,135 @@ public class LocalesTest
}
}
if (Save)
{
string json = JsonConvert.SerializeObject(list, Formatting.Indented);
File.WriteAllText(_spellCheckExcludesPath, json, Encoding.UTF8);
TestContext.Progress.WriteLine($"File spellcheck-excludes.json has been saved to '{_spellCheckExcludesPath}'");
if (Save)
{
string json = JsonConvert.SerializeObject(list, Formatting.Indented);
File.WriteAllText(_spellCheckExcludesPath, json, Encoding.UTF8);
TestContext.Progress.WriteLine($"File spellcheck-excludes.json has been saved to '{_spellCheckExcludesPath}'");
}
Assert.AreEqual(0, errorsCount, message);
}
/* [Test, Order(17)]
[Category("Locales")]
public void UselessModuleTranslationKeysTest()
{
var notFoundi18nKeys = new List<KeyValuePair<string, List<string>>>();
var message = $"Some i18n-keys are not found in Module or Common translations: \r\nKeys: \r\n\r\n";
var index = 0;
for (int i = 0; i < ModuleFolders.Count; i++)
{
var module = ModuleFolders[i];
if (module.AppliedJsTranslationKeys == null && module.AvailableLanguages != null)
{
message += $"{++index}. 'ANY LANGUAGES' '{module.Path}' NOT USED\r\n";
var list = module.AvailableLanguages
.SelectMany(l => l.Translations.Select(t => t.Key).ToList())
.ToList();
notFoundi18nKeys.Add(new KeyValuePair<string, List<string>>("ANY LANGUAGES", list));
continue;
}
var exepts = new List<string> { "Error", "Done", "Warning", "Alert", "Info" };
var notCommonKeys = module.AppliedJsTranslationKeys
.Except(exepts)
.Where(k => !k.StartsWith("Common:"))
.OrderBy(t => t)
.ToList();
var onlyCommonKeys = module.AppliedJsTranslationKeys
.Except(notCommonKeys)
.Select(k => k.Replace("Common:", ""))
.OrderBy(t => t)
.ToList();
notCommonKeys = notCommonKeys.Select(k => k.Substring(k.IndexOf(":") + 1)).ToList();
if (onlyCommonKeys.Any())
{
foreach (var lng in CommonTranslations)
{
var list = onlyCommonKeys
.Except(lng.Translations.Select(t => t.Key))
.ToList();
if (!list.Any())
continue;
message += $"{++index}. '{lng.Language}' '{module.Path}' \r\n {string.Join("\r\n", list)} \r\n";
notFoundi18nKeys.Add(new KeyValuePair<string, List<string>>(lng.Language, list));
}
}
if (module.AvailableLanguages == null)
{
if (notCommonKeys.Any())
{
var commonEnKeys = CommonTranslations.First(c => c.Language == "en").Translations.Select(t => t.Key).ToList();
var list = notCommonKeys
.Except(commonEnKeys.Select(k => k))
.ToList();
if (list.Any())
{
message += $"{++index}. 'ANY LANGUAGES' '{module.Path}' \r\n {string.Join("\r\n", list)} \r\n";
notFoundi18nKeys.Add(new KeyValuePair<string, List<string>>("ANY LANGUAGES", list));
}
}
continue;
}
foreach (var lng in module.AvailableLanguages)
{
var list = lng.Translations
.Select(t => t.Key)
.Except(notCommonKeys)
.ToList();
if (!list.Any())
continue;
message += $"{++index}. '{lng.Language}' '{module.Path}' \r\n {string.Join("\r\n", list)} \r\n";
notFoundi18nKeys.Add(new KeyValuePair<string, List<string>>(lng.Language, list));
}
}
Assert.AreEqual(0, notFoundi18nKeys.Count, message);
}*/
//[Test]
//[Category("Locales")]
//public void TranslationsEncodingTest()
//{
// /*//Convert to UTF-8
// foreach (var issue in WrongEncodingJsonErrors)
// {
// if (issue.DetectionDetail.Encoding == null)
// continue;
// ConvertFileEncoding(issue.Path, issue.Path, issue.DetectionDetail.Encoding, Encoding.UTF8);
// }*/
// var message = $"Next files have encoding issues:\r\n\r\n";
// Assert.AreEqual(0, WrongEncodingJsonErrors.Count,
// message + string.Join("\r\n", WrongEncodingJsonErrors
// .Select(e => $"File path = '{e.Path}' potentially wrong file encoding: {e.DetectionDetail.EncodingName}")));
//}
}
/* [Test, Order(17)]
[Category("Locales")]
public void UselessModuleTranslationKeysTest()
{
var notFoundi18nKeys = new List<KeyValuePair<string, List<string>>>();
var message = $"Some i18n-keys are not found in Module or Common translations: \r\nKeys: \r\n\r\n";
var index = 0;
for (int i = 0; i < ModuleFolders.Count; i++)
{
var module = ModuleFolders[i];
if (module.AppliedJsTranslationKeys == null && module.AvailableLanguages != null)
{
message += $"{++index}. 'ANY LANGUAGES' '{module.Path}' NOT USED\r\n";
var list = module.AvailableLanguages
.SelectMany(l => l.Translations.Select(t => t.Key).ToList())
.ToList();
notFoundi18nKeys.Add(new KeyValuePair<string, List<string>>("ANY LANGUAGES", list));
continue;
}
var exepts = new List<string> { "Error", "Done", "Warning", "Alert", "Info" };
var notCommonKeys = module.AppliedJsTranslationKeys
.Except(exepts)
.Where(k => !k.StartsWith("Common:"))
.OrderBy(t => t)
.ToList();
var onlyCommonKeys = module.AppliedJsTranslationKeys
.Except(notCommonKeys)
.Select(k => k.Replace("Common:", ""))
.OrderBy(t => t)
.ToList();
notCommonKeys = notCommonKeys.Select(k => k.Substring(k.IndexOf(":") + 1)).ToList();
if (onlyCommonKeys.Any())
{
foreach (var lng in CommonTranslations)
{
var list = onlyCommonKeys
.Except(lng.Translations.Select(t => t.Key))
.ToList();
if (!list.Any())
continue;
message += $"{++index}. '{lng.Language}' '{module.Path}' \r\n {string.Join("\r\n", list)} \r\n";
notFoundi18nKeys.Add(new KeyValuePair<string, List<string>>(lng.Language, list));
}
}
if (module.AvailableLanguages == null)
{
if (notCommonKeys.Any())
{
var commonEnKeys = CommonTranslations.First(c => c.Language == "en").Translations.Select(t => t.Key).ToList();
var list = notCommonKeys
.Except(commonEnKeys.Select(k => k))
.ToList();
if (list.Any())
{
message += $"{++index}. 'ANY LANGUAGES' '{module.Path}' \r\n {string.Join("\r\n", list)} \r\n";
notFoundi18nKeys.Add(new KeyValuePair<string, List<string>>("ANY LANGUAGES", list));
}
}
continue;
}
foreach (var lng in module.AvailableLanguages)
{
var list = lng.Translations
.Select(t => t.Key)
.Except(notCommonKeys)
.ToList();
if (!list.Any())
continue;
message += $"{++index}. '{lng.Language}' '{module.Path}' \r\n {string.Join("\r\n", list)} \r\n";
notFoundi18nKeys.Add(new KeyValuePair<string, List<string>>(lng.Language, list));
}
}
Assert.AreEqual(0, notFoundi18nKeys.Count, message);
}*/
//[Test]
//[Category("Locales")]
//public void TranslationsEncodingTest()
//{
// /*//Convert to UTF-8
// foreach (var issue in WrongEncodingJsonErrors)
// {
// if (issue.DetectionDetail.Encoding == null)
// continue;
// ConvertFileEncoding(issue.Path, issue.Path, issue.DetectionDetail.Encoding, Encoding.UTF8);
// }*/
// var message = $"Next files have encoding issues:\r\n\r\n";
// Assert.AreEqual(0, WrongEncodingJsonErrors.Count,
// message + string.Join("\r\n", WrongEncodingJsonErrors
// .Select(e => $"File path = '{e.Path}' potentially wrong file encoding: {e.DetectionDetail.EncodingName}")));
//}
/*[Test]
public void TempTest()
{
@ -1468,8 +1473,8 @@ public class LocalesTest
UpdateKeys(lng.Path, newKeys);
}
}*/
}*/
public static void SaveNotFoundKeys(string pathToJson, List<string> newKeys)
{
if (!File.Exists(pathToJson))
@ -1488,8 +1493,8 @@ public class LocalesTest
var sortedJsonString = JsonConvert.SerializeObject(result, Formatting.Indented);
File.WriteAllText(pathToJson, sortedJsonString, Encoding.UTF8);
}
}
public static void SaveNotFoundLanguage(string existJsonPath, string notExistJsonPath)
{
if (!File.Exists(existJsonPath) || File.Exists(notExistJsonPath))
@ -1513,8 +1518,8 @@ public class LocalesTest
Directory.CreateDirectory(fullPathOnly);
File.WriteAllText(notExistJsonPath, sortedJsonString, Encoding.UTF8);
}
}
public static void UpdateKeys(string pathToJson, List<TranslationItem> newKeys)
{
if (!File.Exists(pathToJson) || !newKeys.Any())
@ -1608,8 +1613,8 @@ public class LocalesTest
var sortedJsonString = JsonConvert.SerializeObject(result, Formatting.Indented);
File.WriteAllText(pathToJson, sortedJsonString, Encoding.UTF8);
}
}
public static Tuple<string, string> getPaths(string language)
{
const string dictionariesPath = @"../../../dictionaries";
@ -1630,84 +1635,84 @@ public class LocalesTest
var affPath = Utils.ConvertPathToOS(Path.Combine(path, language, $"{language}.aff"));
return new Tuple<string, string>(dicPath, affPath);
}
}
public static void ConvertFileEncoding(string sourcePath, string destPath, Encoding sourceEncoding, Encoding destEncoding)
{
// If the destination's parent doesn't exist, create it.
var parent = Path.GetDirectoryName(Path.GetFullPath(destPath));
if (!Directory.Exists(parent))
{
Directory.CreateDirectory(parent);
}
// If the source and destination encodings are the same, just copy the file.
if (sourceEncoding == destEncoding)
{
File.Copy(sourcePath, destPath, true);
return;
}
// Convert the file.
string tempName = null;
try
{
tempName = Path.GetTempFileName();
using (StreamReader sr = new StreamReader(sourcePath, sourceEncoding, false))
{
using (StreamWriter sw = new StreamWriter(tempName, false, destEncoding))
{
int charsRead;
char[] buffer = new char[128 * 1024];
while ((charsRead = sr.ReadBlock(buffer, 0, buffer.Length)) > 0)
{
sw.Write(buffer, 0, charsRead);
}
}
}
File.Delete(destPath);
File.Move(tempName, destPath);
}
finally
{
File.Delete(tempName);
}
public static void ConvertFileEncoding(string sourcePath, string destPath, Encoding sourceEncoding, Encoding destEncoding)
{
// If the destination's parent doesn't exist, create it.
var parent = Path.GetDirectoryName(Path.GetFullPath(destPath));
if (!Directory.Exists(parent))
{
Directory.CreateDirectory(parent);
}
// If the source and destination encodings are the same, just copy the file.
if (sourceEncoding == destEncoding)
{
File.Copy(sourcePath, destPath, true);
return;
}
// Convert the file.
string tempName = null;
try
{
tempName = Path.GetTempFileName();
using (StreamReader sr = new StreamReader(sourcePath, sourceEncoding, false))
{
using (StreamWriter sw = new StreamWriter(tempName, false, destEncoding))
{
int charsRead;
char[] buffer = new char[128 * 1024];
while ((charsRead = sr.ReadBlock(buffer, 0, buffer.Length)) > 0)
{
sw.Write(buffer, 0, charsRead);
}
}
}
File.Delete(destPath);
File.Move(tempName, destPath);
}
finally
{
File.Delete(tempName);
}
}
/* [Test]
public void MoveKeysToCommon()
{
var findKeys = new List<string> {
public void MoveKeysToCommon()
{
var findKeys = new List<string> {
"SharingPanel:CustomFilter",
"SharingPanel:ReadOnly",
"SharingPanel:DenyAccess",
"SharingPanel:Comment",
"SharingPanel:ShareVia"
};
//var findKeys = new List<string> {
// "Translations:DownloadApps",
//};
foreach (var findKey in findKeys)
{
var splitted = findKey.Split(":");
var file = splitted[0];
var key = splitted[1];
var tFiles = TranslationFiles.Where(t => t.FileName.Equals($"{file}.json", StringComparison.InvariantCultureIgnoreCase));
foreach (var tFile in tFiles)
{
var tKeys = tFile.Translations.Where(t => t.Key == key);
foreach (var tKey in tKeys)
{
var commonPath = Utils.ConvertPathToOS(Path.Combine(BasePath, "public/locales", tFile.Language, "Common.json"));
AddKeyValue(commonPath, tKey.Key, tKey.Value);
RemoveKey(tFile.FilePath, key);
}
}
}
"SharingPanel:ShareVia"
};
//var findKeys = new List<string> {
// "Translations:DownloadApps",
//};
foreach (var findKey in findKeys)
{
var splitted = findKey.Split(":");
var file = splitted[0];
var key = splitted[1];
var tFiles = TranslationFiles.Where(t => t.FileName.Equals($"{file}.json", StringComparison.InvariantCultureIgnoreCase));
foreach (var tFile in tFiles)
{
var tKeys = tFile.Translations.Where(t => t.Key == key);
foreach (var tKey in tKeys)
{
var commonPath = Utils.ConvertPathToOS(Path.Combine(BasePath, "public/locales", tFile.Language, "Common.json"));
AddKeyValue(commonPath, tKey.Key, tKey.Value);
RemoveKey(tFile.FilePath, key);
}
}
}
} */
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<babeledit_project be_version="4.1.0" version="1.3">
<babeledit_project be_version="5.2.0" version="1.3">
<!--
BabelEdit project file
@ -26,7 +26,6 @@
<name>BackToRoom</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -158,7 +157,6 @@
<name>Description</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -290,7 +288,6 @@
<name>FillItOutAgain</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -422,7 +419,6 @@
<name>FormNumber</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -554,7 +550,6 @@
<name>Manager</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -686,7 +681,6 @@
<name>Title</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -823,7 +817,6 @@
<name>DeepLinkText</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -955,7 +948,6 @@
<name>OpenInApp</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -1087,7 +1079,6 @@
<name>OpeningDocument</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -1219,7 +1210,6 @@
<name>StayInBrowser</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -1356,7 +1346,6 @@
<name>DocumentsFileType</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -1488,7 +1477,6 @@
<name>ErrorConnectionLost</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -1620,7 +1608,6 @@
<name>FileLocation</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -1752,7 +1739,6 @@
<name>FileName</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -1884,7 +1870,6 @@
<name>ImageFileType</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -2016,7 +2001,6 @@
<name>MailMergeFileType</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -2148,7 +2132,6 @@
<name>OpenSavedDocument</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -2280,7 +2263,6 @@
<name>SelectFilesType</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -2412,7 +2394,6 @@
<name>UsersWithoutAccess</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -2789,6 +2770,7 @@
<code_for_machine_translation/>
</custom_language>
</custom_languages>
<id_extractor_ignores/>
</editor_configuration>
<primary_language>en-US</primary_language>
<configuration>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<babeledit_project be_version="4.1.0" version="1.3">
<babeledit_project be_version="5.2.0" version="1.3">
<!--
BabelEdit project file
@ -26,7 +26,6 @@
<name>ErrorConfirmURLError</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -158,7 +157,6 @@
<name>ErrorExpiredActivationLink</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -290,7 +288,6 @@
<name>ErrorInvalidActivationLink</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -422,7 +419,6 @@
<name>ErrorNotAllowedOption</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -554,7 +550,6 @@
<name>ErrorUserNotFound</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -686,7 +681,6 @@
<name>InvalidUsernameOrPassword</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -818,7 +812,6 @@
<name>LoginWithAccountNotFound</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -950,7 +943,6 @@
<name>LoginWithBruteForce</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -1082,7 +1074,6 @@
<name>LoginWithBruteForceCaptcha</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -1214,7 +1205,6 @@
<name>RecaptchaInvalid</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -1346,7 +1336,6 @@
<name>SsoAttributesNotFound</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -1478,7 +1467,6 @@
<name>SsoAuthFailed</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -1610,7 +1598,6 @@
<name>SsoError</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -1742,7 +1729,6 @@
<name>SsoSettingsCantCreateUser</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -1874,7 +1860,6 @@
<name>SsoSettingsDisabled</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -2006,7 +1991,6 @@
<name>SsoSettingsEmptyToken</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -2138,7 +2122,6 @@
<name>SsoSettingsNotValidToken</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -2270,7 +2253,6 @@
<name>SsoSettingsUserTerminated</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -2407,7 +2389,6 @@
<name>CodeSubtitle</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -2539,7 +2520,6 @@
<name>CodeTitle</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -2671,7 +2651,6 @@
<name>ErrorInvalidText</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -2803,7 +2782,6 @@
<name>ExpiredCode</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -2935,7 +2913,6 @@
<name>ForgotPassword</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -3067,7 +3044,6 @@
<name>InvalidCode</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -3199,7 +3175,6 @@
<name>LDAPUsernamePlaceholder</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -3331,7 +3306,6 @@
<name>MessageAuthorize</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -3463,7 +3437,6 @@
<name>MessageEmailConfirmed</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -3595,7 +3568,6 @@
<name>MessageSendPasswordRecoveryInstructionsOnEmail</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -3727,7 +3699,6 @@
<name>NotFoundCode</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -3859,7 +3830,6 @@
<name>PasswordRecoveryTitle</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -3991,7 +3961,6 @@
<name>RecoverAccess</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -4123,7 +4092,6 @@
<name>RecoverContactEmailPlaceholder</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -4255,7 +4223,6 @@
<name>RecoverTextBody</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -4387,7 +4354,6 @@
<name>Register</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -4519,7 +4485,6 @@
<name>RegisterTextBodyAfterDomainsList</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -4651,7 +4616,6 @@
<name>RegisterTextBodyBeforeDomainsList</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -4783,7 +4747,6 @@
<name>RegisterTitle</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -4915,7 +4878,6 @@
<name>RegistrationEmailWatermark</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -5047,7 +5009,6 @@
<name>RememberHelper</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -5179,7 +5140,6 @@
<name>ResendCode</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -5311,7 +5271,6 @@
<name>SignInLDAP</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -5443,7 +5402,6 @@
<name>SignInLdapHelper</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -5575,7 +5533,6 @@
<name>UserIsAlreadyRegistered</name>
<description/>
<comment/>
<default_text/>
<translations>
<translation>
<language>ar-SA</language>
@ -5952,6 +5909,7 @@
<code_for_machine_translation/>
</custom_language>
</custom_languages>
<id_extractor_ignores/>
</editor_configuration>
<primary_language>en-US</primary_language>
<configuration>

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "مجلد WebDAV",
"FolderTitleYandex": "مجلد Yandex",
"FormTemplates": "قوالب جاهزة",
"LinkCopySuccess": "تم نسخ الرابط إلى الحافظة",
"LinkHasExpiredAndHasBeenDisabled": "تم انتهاء صلاحية الرابط وتم تعطيله",
"LinkValidTime": "هذا الرابط صالح لمدة {{days_count}} أيام فقط.",
"NewForm": "نموذج PDF",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "WebDAV Kataloqu",
"FolderTitleYandex": "Yandex Kataloqu",
"FormTemplates": "Anket şablonları",
"LinkCopySuccess": "Link buferə köçürüldü",
"LinkHasExpiredAndHasBeenDisabled": "Keçidin vaxtı bitib və deaktiv edilib",
"LinkValidTime": "Bu link yalnız {{days_count}} gün ərzində etibarlıdır.",
"NewForm": "PDF forma",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "WebDAV директория",
"FolderTitleYandex": "Yandex директория",
"FormTemplates": "Шаблони на формуляри",
"LinkCopySuccess": "Връзката беше копирана в клипборда",
"LinkHasExpiredAndHasBeenDisabled": "Линкът изтече и беше деактивиран",
"LinkValidTime": "Този линк е валиден само за {{days_count}} дни.",
"NewForm": "PDF формуляр",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "Adresář WebDAV",
"FolderTitleYandex": "Adresář Yandex",
"FormTemplates": "Šablony formulářů",
"LinkCopySuccess": "Odkaz byl zkopírován do schránky",
"LinkHasExpiredAndHasBeenDisabled": "Platnost odkazu vypršela a byl zakázán",
"LinkValidTime": "Tento odkaz je platný pouze po dobu {{days_count}} dnů.",
"NewForm": "PDF formulář",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "WebDAV Verzeichnis",
"FolderTitleYandex": "Yandex Verzeichnis",
"FormTemplates": "Formularvorlagen",
"LinkCopySuccess": "Der Link wurde in die Zwischenablage kopiert",
"LinkHasExpiredAndHasBeenDisabled": "Der Link ist abgelaufen und wurde deaktiviert.",
"LinkValidTime": "Dieser Link ist nur für {{days_count}} Tage gültig.",
"NewForm": "PDF-Formular",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "Κατάλογος WebDAV",
"FolderTitleYandex": "Κατάλογος Yandex",
"FormTemplates": "Πρότυπα φόρμας",
"LinkCopySuccess": "Ο σύνδεσμος έχει αντιγραφεί στο πρόχειρο",
"LinkHasExpiredAndHasBeenDisabled": "Ο σύνδεσμος έχει λήξει και έχει απενεργοποιηθεί",
"LinkValidTime": "Αυτός ο σύνδεσμος ισχύει μόνο για {{days_count}} ημέρες.",
"NewForm": "Φόρμα PDF",

View File

@ -5,5 +5,5 @@
"FillPDFDialogTitle": "Fill in as",
"ShareCollectButtonLabel": "Copy to room",
"ShareCollectDescription": "Share your form and collect responses via a Form filling room.",
"ShareCollectTitle": "Share & collect"
"ShareCollectTitle": "Share"
}

View File

@ -40,6 +40,7 @@
"RoomExternalLinkCreated": "Link created.",
"RoomExternalLinkDeleted": "Link <1>«{{linkTitle}}»</1> deleted.",
"RoomExternalLinkRenamed": "Link <1>«{{oldLinkTitle}}»</1> renamed to <1>«{{linkTitle}}»</1>",
"RoomExternalLinkRevoked": "Previous link <1>«{{linkTitle}}»</1> revoked <br/> New Link <1>«{{linkTitle}}»</1> created",
"RoomGroupAdded": "Groups added.",
"RoomGroupRemove": "Group removed",
"RoomLogoCreated": "Icon changed",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "WebDAV Directory",
"FolderTitleYandex": "Yandex Directory",
"FormTemplates": "Form templates",
"LinkCopySuccess": "Link has been copied to the clipboard",
"LinkHasExpiredAndHasBeenDisabled": "The link has expired and has been disabled",
"LinkValidTime": "This link is valid for {{days_count}} days only.",
"NewForm": "PDF Form",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "Directorio WebDAV",
"FolderTitleYandex": "Directorio Yandex",
"FormTemplates": "Plantillas de formulario",
"LinkCopySuccess": "El enlace se ha copiado en el portapapeles",
"LinkHasExpiredAndHasBeenDisabled": "El enlace ha expirado y se ha desactivado",
"LinkValidTime": "Este enlace solo es válido durante {{days_count}} días.",
"NewForm": "Formulario PDF",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "WebDAV-hakemisto",
"FolderTitleYandex": "Yandex-hakemisto",
"FormTemplates": "Lomakepohjat",
"LinkCopySuccess": "Linkki on kopioitu leikepöydälle",
"LinkHasExpiredAndHasBeenDisabled": "Linkki on vanhentunut ja se on poistettu käytöstä",
"LinkValidTime": "Linkki on voimassa vain {{days_count}} päivää.",
"NewForm": "PDF-lomake",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "Répertoire WebDAV",
"FolderTitleYandex": "Répertoire Yandex",
"FormTemplates": "Modèles de formulaire",
"LinkCopySuccess": "Le lien a été copié dans le Presse-papiers",
"LinkHasExpiredAndHasBeenDisabled": "Le lien a expiré et a été désactivé",
"LinkValidTime": "Ce lien nest valable que pour les {{days_count}} jours.",
"NewForm": "Formulaire PDF",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "WebDAV գրացուցակ",
"FolderTitleYandex": "Yandex գրացուցակ",
"FormTemplates": "Ձեւանմուշներ",
"LinkCopySuccess": "Հղումը պատճենվել է սեղմատախտակին",
"LinkHasExpiredAndHasBeenDisabled": "Այս հղումն ուժի մեջ ",
"LinkValidTime": "Այս հղումը վավեր է միայն {{days_count}} օր:",
"NewForm": "PDF Ձև",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "Cartella di WebDAV",
"FolderTitleYandex": "Cartella di Yandex",
"FormTemplates": "Modelli di moduli",
"LinkCopySuccess": "Il link è stato copiato negli appunti",
"LinkHasExpiredAndHasBeenDisabled": "Il link è scaduto ed è stato disattivato",
"LinkValidTime": "Questo link è valido solo per {{days_count}} giorni.",
"NewForm": "Modulo PDF",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "WebDAVディレクトリ",
"FolderTitleYandex": "Yandexディレクトリ",
"FormTemplates": "フォームのテンプレート",
"LinkCopySuccess": "リンクがクリップボードにコピーされました",
"LinkHasExpiredAndHasBeenDisabled": "リンクは有効期限が切れたため無効になっています",
"LinkValidTime": "このリンクは {{days_count}} 日間のみ有効です。",
"NewForm": "PDFフォーム",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "WebDAV 디렉토리",
"FolderTitleYandex": "Yandex 디렉토리",
"FormTemplates": "양식 템플릿",
"LinkCopySuccess": "링크가 클립보드에 복사되었습니다",
"LinkHasExpiredAndHasBeenDisabled": "링크가 만료되어 비활성화되었습니다",
"LinkValidTime": "이 링크는 {{days_count}}일 동안만 유효합니다.",
"NewForm": "PDF 양식",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "ໄດເລກະທໍລີ WebDAV",
"FolderTitleYandex": "ໄດເລກະທໍລີ Yandex",
"FormTemplates": "ຮູບແບບແບບຟອມ",
"LinkCopySuccess": "ລິ້ງໄດ້ຖືກສໍາເນົາໄປ clipboard",
"LinkValidTime": "ລິ້ງນີ້ໃຊ້ໄດ້ເປັນເວລາ {{days_count}} ມື້ເທົ່ານັ້ນ.",
"NewForm": "ແບບຟອມ PDF",
"Other": "ອື່ນໆ",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "WebDAV direktorijs",
"FolderTitleYandex": "Yandex direktorijs",
"FormTemplates": "Veidlapu veidnes",
"LinkCopySuccess": "Saite ir nokopēta starpliktuvē",
"LinkHasExpiredAndHasBeenDisabled": "Saitei ir beidzies derīguma termiņš, un tā ir atspējota",
"LinkValidTime": "Šī saite ir derīga tikai {{days_count}} dienu (-as).",
"NewForm": "PDF veidlapa",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "WebDAV Directory",
"FolderTitleYandex": "Yandex Directory",
"FormTemplates": "Formulier sjablonen",
"LinkCopySuccess": "Link is gekopieerd naar het klembord",
"LinkHasExpiredAndHasBeenDisabled": "De link is verlopen en uitgeschakeld",
"LinkValidTime": "Deze link is slechts {{days_count}} dagen geldig.",
"NewForm": "PDF-formulier",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "Katalog WebDAV",
"FolderTitleYandex": "Katalog Yandex",
"FormTemplates": "Szablony formularza",
"LinkCopySuccess": "Link został skopiowany do schowka",
"LinkHasExpiredAndHasBeenDisabled": "Link wygasł i został wyłączony",
"LinkValidTime": "Link jest ważny tylko przez {{days_count}} dni.",
"NewForm": "Formularz PDF",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "Diretório WebDAV",
"FolderTitleYandex": "Diretório Yandex",
"FormTemplates": "Modelos de formulário",
"LinkCopySuccess": "Link foi copiado para a área de trabalho",
"LinkHasExpiredAndHasBeenDisabled": "O link expirou e foi desativado",
"LinkValidTime": "Este link é válido apenas por {{days_count}} dias.",
"NewForm": "Formulário PDF",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "Diretório WebDAV",
"FolderTitleYandex": "Diretório Yandex",
"FormTemplates": "Modelos de formulário",
"LinkCopySuccess": "A ligação foi copiada para a área de transferência",
"LinkHasExpiredAndHasBeenDisabled": "O link expirou e foi desativado",
"LinkValidTime": "Esta hiperligação é válida apenas por {{days_count}} dias.",
"NewForm": "Formulário PDF",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "Director WebDAV",
"FolderTitleYandex": "Director Yandex",
"FormTemplates": "Șabloane formular",
"LinkCopySuccess": "Încărcarea fișierului media eșuată",
"LinkHasExpiredAndHasBeenDisabled": "Link-ul a expirat și este dezactivat",
"LinkValidTime": "Acest link este valabil doar timp de {{days_count}} zile.",
"NewForm": "Formular PDF",

View File

@ -285,7 +285,7 @@
"TypesAndPrivileges": " <1>Типы учетных записей администратора и их права</1> <br> <br> <2>Администратор {{productName}}</2> <br> Настройка {{productName}}, создание и управление комнатами, возможность приглашать пользователей и управлять ими в {{productName}} и в виртуальных комнатах, возможность управления правами доступа. <br> <br> <3>Администратор комнаты</3> <br> Администрирование и архивирование комнаты, приглашение пользователей и управление ими. К комнате можно назначить нескольких администраторов. <br> <br> <4>Опытный пользователь</4> <br> Опытные пользователи могут создавать и редактировать файлы в комнате, но не могут создавать комнаты, управлять пользователями или получать доступ к настройкам.",
"UnsavedChangesBody": "Если вы закроете меню настроек ссылки прямо сейчас, изменения не сохранятся.",
"UnsupportedFilesDescription": "Некоторые резервные файлы не поддерживаются. Нажмите \"Проверьте неподдерживаемые файлы\", чтобы загрузить список неподдерживаемых элементов",
"UnsupportedFilesWithUploadDesc": "Некоторые резервные файлы не поддерживаются. Нажмите \\\"Проверьте неподдерживаемые файлы\\\", чтобы загрузить список неподдерживаемых элементов, или нажмите \\\"Загрузить на сервер\\\", чтобы продолжить без них.",
"UnsupportedFilesWithUploadDesc": "Некоторые резервные файлы не поддерживаются. Нажмите \"Проверьте неподдерживаемые файлы\", чтобы загрузить список неподдерживаемых элементов, или нажмите \"Загрузить на сервер\", чтобы продолжить без них.",
"UpdatingStatistics": "Обновление статистики может занять много времени",
"UploadBackupData": "Загрузите резервную копию из нужного сервиса ниже, чтобы начать миграцию.",
"UploadToServer": "Загрузить на сервер",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "Каталог WebDAV",
"FolderTitleYandex": "Каталог Яндекса",
"FormTemplates": "Шаблоны форм",
"LinkCopySuccess": "Ссылка скопирована в буфер обмена",
"LinkHasExpiredAndHasBeenDisabled": "Срок действия ссылки истек, она отключена",
"LinkValidTime": "Эта ссылка действительна только {{days_count}} дней.",
"NewForm": "PDF-форма",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "WebDAV නාමාවලිය",
"FolderTitleYandex": "යාන්ඩෙක්ස් නාමාවලිය",
"FormTemplates": "ආකෘතිපත්‍ර අච්චු",
"LinkCopySuccess": "සබැඳිය පසුරුපුවරුවට පිටපත් විය",
"LinkHasExpiredAndHasBeenDisabled": "සබැඳිය කල් ඉකුත් වී අබල කර ඇත",
"LinkValidTime": "මෙම සබැඳිය දවස් {{days_count}}කට වලංගුය.",
"NewForm": "ආකෘතිපත්‍ර අච්චුව",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "Priečinok WebDAV",
"FolderTitleYandex": "Priečinok Yandex",
"FormTemplates": "Šablóny formulára",
"LinkCopySuccess": "Odkaz bol skopírovaný do schránky",
"LinkHasExpiredAndHasBeenDisabled": "Platnosť odkazu vypršala a bol deaktivovaný",
"LinkValidTime": "Tento odkaz je platný iba {{days_count}} dní.",
"NewForm": "Formulár PDF",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "WebDAV direktorij",
"FolderTitleYandex": "Yandex direktorij",
"FormTemplates": "Predloge obrazcev",
"LinkCopySuccess": "Povezava je bila kopirana v odložišče",
"LinkHasExpiredAndHasBeenDisabled": "Povezava je potekla in je onemogočena",
"LinkValidTime": "Ta povezava je veljavna le {{days_count}} dni.",
"NewForm": "PDF obrazec",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "WebDAV директоријум",
"FolderTitleYandex": "Yandex директоријум",
"FormTemplates": "Шаблони образаца",
"LinkCopySuccess": "Линк је копиран на привремену меморију",
"LinkHasExpiredAndHasBeenDisabled": "Линк је истекао и онемогућен је",
"LinkValidTime": "Овај линк је валидан само за {{days_count}} дана",
"NewForm": "PDF образац",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "WebDAV direktorijum",
"FolderTitleYandex": "Yandex direktorijum",
"FormTemplates": "Šabloni obrazaca",
"LinkCopySuccess": "Link je kopiran na privremenu memoriju",
"LinkHasExpiredAndHasBeenDisabled": "Link je istekao i onemogućen je",
"LinkValidTime": "Ovaj link je validan samo za {{days_count}} dana",
"NewForm": "PDF obrazac",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "WebDAV Dizini",
"FolderTitleYandex": "Yandex Dizini",
"FormTemplates": "Form şablonları",
"LinkCopySuccess": "Bağlantı panoya kopyalandı",
"LinkHasExpiredAndHasBeenDisabled": "Bağlantının süresi doldu ve devre dışı bırakıldı",
"LinkValidTime": "Bu bağlantı yalnızca {{days_count}} gün için geçerlidir.",
"NewForm": "PDF formu",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "Каталог WebDAV",
"FolderTitleYandex": "Каталог Yandex",
"FormTemplates": "Шаблони форми",
"LinkCopySuccess": "Посилання скопійовано до буферу обміну",
"LinkHasExpiredAndHasBeenDisabled": "Термін дії посилання закінчився, і його було вимкнено",
"LinkValidTime": "Це посилання дійсне лише протягом {{days_count}} дн.",
"NewForm": "Форма PDF",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "Thư mục WebDAV",
"FolderTitleYandex": "Thư mục Yandex",
"FormTemplates": "Mẫu biểu mẫu",
"LinkCopySuccess": "Liên kết đã được sao chép vào bộ nhớ tạm",
"LinkHasExpiredAndHasBeenDisabled": "Liên kết đã hết hạn và đã bị vô hiệu hóa",
"LinkValidTime": "Liên kết này chỉ có giá trị trong {{days_count}} ngày.",
"NewForm": "Mẫu PDF",

View File

@ -1,7 +1,14 @@
{
"AppointAdmin": "预约管理员",
"BackupPortal": " 备份{{productName}}数据",
"ChangeInstruction": " 要更改{{productName}}所有者,请在下面选择新所有者的姓名。",
"ChangeOwner": " 更改{{productName}}所有者",
"ChangeUser": "变更用户",
"DeactivateOrDeletePortal": " 停用或删除{{productName}}",
"DoTheSame": "与管理员进行相同操作",
"ManagePortal": " 管理{{productName}}配置",
"ManageUser": "管理用户账户",
"NewPortalOwner": " 新{{productName}}所有者",
"PortalOwnerCan": " {{productName}}所有者可以:",
"SetAccessRights": "设置访问权限"
}

View File

@ -1,7 +1,11 @@
{
"DisableGeneralDescription": "如有需要,您可以稍后删除或启用已禁用的用户。请注意,您无法禁用某些用户,如所有者和您自己。",
"DisableUser": "禁用用户",
"DisableUserDescription": " 如果您禁用此用户,他们将无法登录{{productName}},但他们的文档和数据将保持不变。",
"DisableUsers": "禁用用户",
"DisableUsersDescription": " 如果您禁用这些用户,他们将无法登录{{productName}},但他们的文档和数据将保持不变。",
"EnableUser": "启用用户",
"EnableUsers": "启用用户"
"EnableUserDescription": " 如果您启用此用户,他们将能够再次登录{{productName}}并访问他们的文档和数据。",
"EnableUsers": "启用用户",
"EnableUsersDescription": "如果您启用这些用户,他们将能够再次登录{{productName}}并访问他们的文档和数据。"
}

View File

@ -3,5 +3,6 @@
"ChangeUserTypeHeader": "变更用户类型",
"ChangeUserTypeMessage": "{{ firstType }}’类型的用户将被移动至‘{{ secondType }}’类型。",
"ChangeUserTypeMessageMulti": "选择的用户将被移动至'{{ secondType }}'类型。",
"ChangeUserTypeMessageWarning": " 您无法更改{{productName}}管理员和您自己的类型。",
"SuccessChangeUserType": "用户类型已成功变更"
}

View File

@ -1,9 +1,13 @@
{
"AccountWillBeCreated": " 将为 <1>{{email}}</1>创建{{productName}}帐户。请完成您的注册:",
"ChangePasswordSuccess": "密码已成功更改",
"ConfirmOwnerPortalSuccessMessage": " {{productName}}所有者已成功更改。您将于 10 秒后被重定向。",
"ConfirmOwnerPortalTitle": "请确认您要将{{productName}}所有者更改为{{newOwner}}。",
"CurrentNumber": "您目前的手机号码",
"DeleteProfileBtn": "删除我的账户",
"DeleteProfileConfirmation": "注意!您即将删除账户。",
"DeleteProfileConfirmationInfo": "点击“删除我的账户”即表示您同意我们的 <1>隐私政策。</1>",
"DeleteProfileSuccessDescription": " 您的{{productName}}帐户已成功禁用。{{productName}}所有者或管理员可以永久删除您已禁用的帐户。",
"DeleteProfileSuccessMessage": "您的账户已成功删除。",
"DeleteProfileSuccessMessageInfo": "请查看我们的<1>隐私政策</1>以了解有关删除账户及其相关数据的更多信息。",
"EmailAndPasswordCopiedToClipboard": "邮箱和密码已复制到剪贴板",
@ -14,8 +18,13 @@
"GetCode": "获取代码",
"LoginRegistryButton": "加入",
"PassworResetTitle": "现在您可创建新密码。",
"PhoneSubtitle": " 启用双重身份验证以提供额外的安全性。输入您的手机号码以继续在{{productName}}中工作。必须使用带有国家代码的国际格式输入手机号码。",
"PortalContinueTitle": " 请确认您要重新激活您的{{productName}}。",
"PortalDeactivateTitle": " 请确认您要停用您的{{productName}}。",
"PortalRemoveTitle": " 请确认您要删除您的{{productName}}。",
"Reactivate": "重新激活",
"SetAppButton": "连接应用",
"SetAppDescription": " 双重身份验证已启用。配置您的身份验证器应用以继续在{{productName}}中工作。您可以使用适用于 <1>Android</1> 和 <4>iOS</4> 的 Google Authenticator 或适用于 <8>Windows Phone</8> 的 Authenticator。",
"SetAppInstallDescription": "如需连接应用,请扫描二维码或手动输入您的密钥<1>{{ secretKey }}</1>然后在下方的字段中输入应用中的6位数字码。",
"SetAppTitle": "配置您的身份验证应用",
"SignUp": "注册",

View File

@ -1,11 +1,15 @@
{
"ActivationRequired": " 需要激活",
"ChooseRoomType": "选择房间类型",
"CreateRoomConfirmation": "继续且不连接存储?\n您已选择尚未连接的第三方存储选项。如果在未连接服务的情况下继续则不会添加此选项。",
"CreateTagOption": "创建标签",
"DisableRoomQuota": "停用该房间的配额",
"FormRoomBarDescription": " 此房间可供任何有链接的人使用。外部用户将拥有所有文件的填表权限。",
"Icon": "图标",
"MakeRoomPrivateDescription": "此房间中的所有文件都将被加密。",
"MakeRoomPrivateLimitationsWarningDescription": " 使用此功能,您只能邀请现有的{{productName}}用户。创建房间后,您将无法更改用户列表。",
"MakeRoomPrivateTitle": "将房间设为私密",
"PeopleSelectorInfo": " 只有房间管理员或{{productName}}管理员才能成为房间的所有者",
"PublicRoomBarDescription": "所有人都可以通过链接进入此房间。外部用户拥有“仅查看”权限,可查看所有文件",
"PublicRoomSystemFoldersDescription": "不同完成阶段的表单副本存储在“系统”文件夹中。正在填写的表单存储在“处理中”文件夹中,填写完成的表单存储在“完成”文件夹中。",
"PublicRoomSystemFoldersTitle": "系统文件夹",
@ -16,5 +20,6 @@
"ThirdPartyStorageComboBoxPlaceholder": "选择存储空间",
"ThirdPartyStorageDescription": "为此房间的数据存储使用第三方服务。将在已连接的存储空间中创建一个用于存储此房间数据的新文件夹。",
"ThirdPartyStorageNoStorageAlert": "您需要在此之前于“集成”部分中连接相应服务。否则将无法建立连接。",
"ThirdPartyStoragePermanentSettingDescription": "文件已存储在第三方 {{thirdpartyTitle}} 存储空间的\"{{thirdpartyFolderName}}\"文件夹中。\n<strong>{{thirdpartyPath}}</strong>"
"ThirdPartyStoragePermanentSettingDescription": "文件已存储在第三方 {{thirdpartyTitle}} 存储空间的\"{{thirdpartyFolderName}}\"文件夹中。\n<strong>{{thirdpartyPath}}</strong>",
"ThirdPartyStorageRoomAdminNoStorageAlert": " 要连接第三方存储,您需要在{{productName}}设置的集成部分中添加相应的服务。联系{{productName}}所有者或管理员以启用集成。"
}

View File

@ -1,7 +1,9 @@
{
"DeleteAllGroupDescription": "所选组将被删除。组中的用户不会从{{productName}}中删除。您确定要继续吗?",
"DeleteAllGroupsTitle": "删除群组",
"DeleteFile": "您即将删除此文件。",
"DeleteFolder": "您即将删除此文件夹。",
"DeleteGroupDescription": " 组{{groupName}} 将被删除。组中的用户不会从{{productName}}中删除。您确定要继续吗?",
"DeleteGroupTitle": "删除群组",
"DeleteItems": "您即将删除这些项目。",
"DeleteItemsSharedNote": "请注意,如果您已将它们分享给他人,它们将不可用。",

View File

@ -1,7 +1,10 @@
{
"ActionCannotBeUndone": " 所选的已禁用用户将从{{productName}}中删除。此操作无法撤消。",
"CannotReassignFiles": "如果您一次删除了多个用户,则无法将他们的文件重新分配给其他用户。",
"DeleteGroupUsersSuccessMessage": "用户已成功删除。",
"DeleteMyDocumentsUser": "该用户“我的文档”板块中的所有个人文件和文件夹将被永久删除。",
"DeletePersonalData": " 选定用户的“文档”和“垃圾箱”部分*中的个人数据、所有个人文件和文件夹将被永久删除。选定用户保存在公共部分*(如房间)中的文件和文件夹将保留在{{productName}}中。",
"DeletePersonalDataApplicable": " *适用于拥有此类文件和文件夹的选定用户。",
"DeleteReassignDescriptionUser": "此用户创建的 {{warningMessageMyDocuments}} 房间及存储在房间中的文档将被自动转让给执行删除操作的管理员:<strong>{{userPerformedDeletion}} ({{userYou}})</strong>。您可以手动转让数据,选择其他转让目标用户。",
"DeleteUser": "删除用户",
"DeleteUserMessage": "{{userCaption}} <strong>{{user}}</strong> 将被删除。此操作无法撤消。",

View File

@ -1,4 +1,5 @@
{
"DeleteOwnerRestrictionText": "作为此{{productName}}的所有者,您必须将所有权转让给其他用户,然后才能禁用您的帐户。请选择新所有者以继续。",
"DeleteProfileInfo": "将档案删除指示发送至邮件地址",
"DeleteProfileTitle": "禁用帐户"
}

View File

@ -2,5 +2,6 @@
"CannotChangePlan": "由于已使用的存储量或管理员/高级用户的数量超过了所选方案的限制,您无法改变方案:",
"ChangePricingPlan": "改变定价方案",
"PlanStorageLimit": "新定价方案的存储量为 <1>{{storageValue}}</1>,而您目前使用的存储量为 <1>{{currentStorageValue}}</1>。",
"PlanUsersLimit": " 您希望将团队降级为 <1>{{usersCount}}</1> 管理员/高级用户,并且您{{productName}}中当前此类用户的数量为 <1>{{currentUsersCount}}</1>。",
"SaveOrChange": "要更改目前的定价方案,请确保您的需求与该方案所提供的服务相符。"
}

View File

@ -1,4 +1,11 @@
{
"CodeSuccessfullyCopied": " 插入代码已成功复制到剪贴板",
"ContentRestricted": " 内容复制、文件下载和打印受到限制。",
"DisplaySettings": " 显示设置",
"EmbeddingBarAllowList": " 将要嵌入的网站 URL 添加到<1>允许列表</1>。",
"EmbeddingBarDescription": "嵌入仅适用于 JavaScript SDK 设置中{{productName}}管理员指定的 URL。",
"Height": "高度",
"Link": " 链接",
"LinkProtectedWithPassword": " 该链接受密码保护。",
"Width": "宽度"
}

View File

@ -1 +1,25 @@
{}
{
"CollaboratorEmptyDesciprtion": " 开始使用快速操作:",
"CollaboratorEmptyTitle": " 房间是空的。",
"CreateNewFileDescription": " 通过创建文件或文件夹开始在房间中工作",
"CreateNewFileTitle": " 创建新文件",
"CustomRoomEmptyTitle": " 欢迎来到自定义房间",
"EmptyDescription": " 开始使用快速操作:",
"FormFolderDefaultDescription": " 将 PDF 表单拖放到此处或从{{productName}}或设备上传。",
"FormFolderDefaultTitle": " 此处尚无表单",
"FormFolderDefaultUserDescription": " 管理员上传的表单将显示在此处。",
"FormFolderDefaultUserTitle": " 此文件夹中尚无表单",
"FormRoomEmptyTitle": " 欢迎来到表单填写房间",
"InviteUsersOptionDescription": " 添加门户成员以便在房间中联合编辑",
"InviteUsersOptionTitle": " 邀请与会者",
"ShareOptionDescription": " 复制公共访问链接或邀请其他用户加入房间以开始表单填写流程。",
"ShareOptionTitle": " 共享房间",
"UploadDeviceOptionDescription": " 从您的个人设备上传任何类型的文件",
"UploadDeviceOptionTitle": " 从您的设备上传",
"UploadDevicePDFFormOptionDescription": " 从您的设备将准备好的 PDF 表单上传到房间。",
"UploadDevicePDFFormOptionTitle": " 从设备上传",
"UploadFromPortalDescription": " 从文档或房间上传任何类型的文件",
"UploadFromPortalTitle": " 从{{productName}}上传",
"UploadPDFFormOptionDescription": " 选择{{productName}}中可用的现成 PDF 表单并将其上传到房间。",
"UserEmptyDescription": " 管理员上传的文件和文件夹将显示在此处。"
}

View File

@ -1,5 +1,6 @@
{
"ErrorEmptyResponse": "空响应",
"ErrorUnavailableText": " {{productName}}不可用",
"LinkDoesNotExist": "链接不存在。",
"LinkHasExpired": "您关注的链接已过期。"
}

View File

@ -7,6 +7,7 @@
"AppointNewOwner": "您已指定一个新的所有者。",
"ArchiveAction": "清空归档",
"ArchivedRoomsAction": "房间已归档",
"ArchiveEmptyScreen": " 您可以随时存档不使用的房间并在{{productName}}中恢复它们,也可以永久删除它们。这些房间将显示在此处。",
"ArchiveEmptyScreenHeader": "此处暂无已归档房间",
"ArchiveEmptyScreenUser": "已归档房间将出现在此处。",
"Archives": "归档",
@ -29,6 +30,7 @@
"CopyLinkPassword": "复制链接密码",
"CopyPassword": "复制密码",
"CopySharedLink": "复制共享链接",
"CreateNewFolder": " 创建新文件夹",
"CreateNewFolderInStorage": "在存储空间中创建一个新文件夹",
"CreateNewLink": "创建新链接",
"CreateRoom": "创建房间",
@ -46,6 +48,7 @@
"EditLink": "编辑链接",
"EditRoom": "编辑房间",
"EditSharedLink": "编辑分享链接",
"Embed": " 嵌入",
"EmbeddingSettings": "嵌入设置",
"EmptyFile": "空文件",
"EmptyFilterSubheadingText": "此过滤条件下无可在此处展示的文件",
@ -59,6 +62,7 @@
"EmptyFormSubFolderHeaderText": "此文件夹中还没有文件",
"EmptyFormSubFolderProgressDescriptionText": "您可以在此处看到处理中的表单,即用户已开始填写但尚未完成的表单。",
"EmptyRecycleBin": "清空垃圾箱",
"EmptyRootRoomHeader": " 欢迎使用{{productName}}",
"EmptyScreenFolder": "未找到任何文档",
"EnableLink": "启用链接",
"EnableNotifications": "启用消息通知",
@ -88,6 +92,7 @@
"LinkDisabledSuccessfully": "链接禁用成功",
"LinkEditedSuccessfully": "已成功编辑和复制链接",
"LinkEnabledSuccessfully": "链接启用成功",
"LinkForPortalUsers": " {{productName}}用户的链接",
"LinkSettings": "链接设置",
"LinkSuccessfullyCreatedAndCopied": "链接已成功创建并复制到剪贴板",
"LinkValidUntil": "链接有效期至",
@ -123,6 +128,7 @@
"PrivateRoomDescriptionUnbreakable": "牢不可破的AES-256算法。",
"PrivateRoomHeader": "欢迎来到{{organizationName}}私密房间,在这里您所输入的每一个字符都将被加密",
"PrivateRoomSupport": "您可在{{organizationName}}桌面应用中使用私密房间。<3>操作指南</3>",
"Protected": "受保护",
"RecentlyAccessible": "最近可通过链接访问的",
"RecentViaLinkEmptyContainerDescription": "您可以在此处查看近期打开的、通过外部链接与您共享的文件的列表。",
"RemovedFromFavorites": "已从收藏中删除",
@ -131,6 +137,7 @@
"RestoreAll": "全部还原",
"RevokeLink": "撤销链接",
"RoomAvailableViaExternalLink": "可通过外部链接访问的房间",
"RoomAvailableViaSharedLink": "房间可通过共享链接使用",
"RoomCreated": "房间已创建",
"RoomEmptyAtTheMoment": "这个房间目前是空的。",
"RoomEmptyContainerDescription": "请创建首个房间。",
@ -140,6 +147,7 @@
"RoomOwner": "房间所有者",
"RoomPinned": "房间已置顶",
"RoomRemoved": "房间已删除",
"RoomsPinLimitMessage": "您不能将超过 10 个房间固定在顶部。取消固定一些当前固定的房间。",
"RoomsPinned": "已固定的房间:{{count}}",
"RoomsRemoved": "房间已删除",
"RoomsUnpinned": "未固定的房间:{{count}}",
@ -148,6 +156,8 @@
"SendByEmail": "通过邮件发送",
"ShareFolder": "共享文件夹",
"ShareFolderDescription": "系统会创建一个新房间,并将所选文件夹的所有内容复制到其中。之后,您可以邀请其他用户在房间内协作处理文件。",
"SharePDFFormModalDescription": "将创建一个新房间,并将 PDF 表单复制到其中。然后,您可以邀请其他用户在房间中填写表单。",
"SharePDFFormModalTitle": "共享 PDF 表单",
"ShareRoom": "分享房间",
"ShowLinkActions": "显示链接操作",
"ShowVersionHistory": "显示版本历史记录",
@ -166,6 +176,7 @@
"VersionHistory": "版本历史",
"ViewList": "列表",
"ViewTiles": "卡片",
"WaitOperation": "等待当前操作完成",
"WantLeaveRoom": "您确定要退出房间吗?您可以通过房间管理员的新邀请再次加入。",
"WantToRestoreTheRoom": "此房间的所有外部链接都会变为活动状态,所有拥有此链接的人都可以访问房间内容。要还原房间吗?",
"WantToRestoreTheRooms": "恢复房间后,其所有的共享链接都将重新生效,并且拥有房间链接的人都可以访问其内容。 您确定恢复房间吗?",

View File

@ -6,6 +6,7 @@
"DisplayTemplates": "显示模板",
"IntermediateVersion": "保留所有已保存的中间版本",
"KeepIntermediateVersion": "编辑时保留中间版本",
"OpenSameTab": "在同一选项卡中打开 {{organizationName}} 编辑器",
"OriginalCopy": "以原始格式保存文件副本",
"StoringFileVersion": "保存文件版本",
"ThirdPartyAccounts": "第三方账户",

View File

@ -1 +1,9 @@
{}
{
"FillOutButtonLabel": "填写",
"FillOutDescription": "在编辑器窗口中填写原始表单的字段。",
"FillOutTitle": "自己填写表单",
"FillPDFDialogTitle": "填写为",
"ShareCollectButtonLabel": "复制到房间",
"ShareCollectDescription": "通过表单填写房间共享您的表单并收集回复",
"ShareCollectTitle": "共享"
}

View File

@ -30,6 +30,7 @@
"HotkeysPlayPause": "播放/暂停",
"HotkeysRedoLastUndoneAction": "重做上次撤销的行动",
"HotkeysRemove": "删除选定的项目",
"HotkeysRenameSelected": "重命名所选项目",
"HotkeysSelectAll": "选择所有可见的文件夹和文件",
"HotkeysSelectDown": "向下选择下一个项目",
"HotkeysSelection": "选择项目",

View File

@ -1,25 +1,59 @@
{
"AccountsEmptyScreenText": "在此查看用户详情",
"AddedRoomTags": "已添加标签。",
"Administration": "管理",
"AndMoreLabel": "以及<1>另外 {{count}} 个</1>",
"CreationDate": "创建日期",
"Data": "数据",
"DateModified": "修改日期",
"DeletedRoomTags": "已删除标签。",
"ExpectUsers": "等待用户",
"FeedLinkWasDeleted": "已删除链接",
"FeedLocationLabel": "文件夹 «{{folderTitle}}»",
"FeedLocationRoomLabel": "房间«{{folderTitle}}»",
"FileConverted": "文件已转换。",
"FileCopied": "文件已复制。",
"FileCreated": "文件已创建。",
"FileDeleted": "文件已删除。",
"FileExtension": "文件扩展名",
"FileMoved": "文件已移动。",
"FileRenamed": "文件已重命名。",
"FilesEmptyScreenText": "在此查看文件和文件夹的详细信息",
"FileUploaded": "文件已添加。",
"FolderCopied": "文件夹已复制。",
"FolderCreated": "文件夹已创建。",
"FolderDeleted": "文件夹已删除。",
"FolderMoved": "文件夹已移动。",
"FolderRenamed": "文件夹已重命名。",
"GalleryEmptyScreenText": "请在此处查看表单模板的详细信息",
"GroupsEmptyScreenText": "在此查看群组详细信息",
"HistoryEmptyScreenText": "活动历史记录将在这里显示",
"HistoryRoomCopied": "<1>«{{roomTitle}}»</1>房间已复制",
"HistoryRoomCreated": "<1>«{{roomTitle}}»</1>房间已创建",
"HistoryThirdParty": "历史记录显示不适用于已连接第三方存储的公共房间",
"InfoBanner": "受邀用户列表包括此{{productName}}的所有者和/或管理员,他们拥有所有房间的完全访问权限。所有者和/或管理员不能被分配其他访问权限。一旦添加到房间,他们将收到所有更改的通知。",
"ItemsSelected": "选定的项目",
"LastModifiedBy": "上次修改时间",
"NoRecordsFound": "未找到记录",
"Properties": "属性",
"RoomCreateUser": "用户已添加。",
"RoomExternalLinkCreated": "链接已创建。",
"RoomExternalLinkDeleted": "链接<1>«{{linkTitle}}»</1>已删除。",
"RoomExternalLinkRenamed": "链接<1>«{{oldLinkTitle}}»</1>重命名为<1>«{{linkTitle}}»</1>",
"RoomGroupAdded": "组已添加。",
"RoomGroupRemove": "组已删除",
"RoomLogoCreated": "图标已更改",
"RoomLogoDeleted": "图标已更改",
"RoomRemoveUser": "用户已删除。",
"RoomRenamed": "房间<1>«{{oldRoomTitle}}»</1>已重命名为<1>«{{roomTitle}}»</1>",
"RoomsEmptyScreenTent": "在此查看房间详情",
"RoomUpdateAccessForGroup": "已分配角色",
"RoomUpdateAccessForUser": "已分配角色",
"SelectedUsers": "已选账户",
"StorageType": "存储类型",
"SubmenuDetails": "详情",
"SubmenuHistory": "历史记录",
"UserFileUpdated": "文件已更新。",
"Users": "用户",
"Versions": "版本"
}

View File

@ -1,10 +1,14 @@
{
"AddManually": "手动添加",
"AddManuallyDescriptionAccounts": "通过电子邮件亲自邀请新用户加入{{productName}}",
"AddManuallyDescriptionRoom": "使用名称将现有{{productName}}用户添加到房间或通过电子邮件亲自邀请新用户",
"EmailErrorMessage": "邮件地址无效。您可点击邮件以进行编辑。",
"GroupMaxAvailableRoleWarning": "可以将群组添加到房间,最大角色为{{roleName}}。但是,成功添加群组后,您可以更改群组中各个用户的角色。",
"InvitationLanguage": "邀请语言",
"InviteAccountSearchPlaceholder": "通过邮件进行邀请",
"InviteRoomSearchPlaceholder": "根据姓名或邮件邀请用户",
"InviteViaLink": "通过链接进行邀请",
"InviteViaLinkDescriptionAccounts": "在{{productName}}中创建用于自我授权的通用链接",
"InviteViaLinkDescriptionRoom": "在房间中创建自我授权通用链接",
"LinkCopySuccess": "链接已复制",
"ResetChange": "重置更改",

View File

@ -4,6 +4,8 @@
"AddWatermarks": "为文档添加水印",
"AdvancedDisplay": "高级显示设置",
"AllTypes": "所有类型",
"AllTypesAvailableForEditing": "{{organizationName}} 中可供编辑的所有文件类型",
"AllTypesSupportedByEditor": "{{organizationName}} 编辑器支持的所有类型",
"APILink": "API库",
"Ascending": "升序",
"ButtonColor": "按钮颜色",
@ -16,12 +18,18 @@
"CopyWindowCode": "复制窗口嵌入代码",
"CreateSampleEditor": "创建示例编辑器嵌入",
"CreateSampleFileSelector": "创建示例文件选择器嵌入",
"CreateSamplePortal": "创建示例{{productName}}嵌入",
"CreateSamplePublicRoom": "创建示例公共房间嵌入",
"CreateSampleRoomSelector": "创建示例房间选择器嵌入",
"CreateSampleViewer": "创建示例查看器嵌入",
"CSPDescription": "要开始嵌入过程,请将{{productName}}URL 添加到允许列表。",
"CSPHeader": "输入要嵌入的{{productName}}地址",
"CSPHelp": "该设置是一种安全措施可用于防范内容注入攻击。CSP 描述了安全的资源下载源。从未列在\"白名单\"中的资源下载将被阻止。指定域和与之配合的协议。",
"CSPInfoBarDescription": "请为您的{{productName}}启用 HTTPS 协议,以确保正确设置工作。",
"CSPInfoBarHeader": "需要 HTTPS",
"CSPInputPlaceholder": "输入同类格式的链接 URL https://example.com",
"CSPUrlHelp": "输入{{productName}}域名,不带 URL 路径或其他字符。",
"CustomDescription": "手动配置嵌入{{productName}}的参数。",
"CustomizingDisplay": "自定义显示",
"DataDisplay": "数据显示设置",
"DefaultColumnsOption": "默认(数量取决于屏幕宽度)",
@ -38,6 +46,7 @@
"EnterWidth": "输入宽度",
"FeedbackAndSupport": "反馈与支持",
"FileContentCopy": "文件内容复制限制",
"FileFilter": "文件过滤器",
"FileId": "文件 ID",
"FilePreview": "文件预览",
"FileSelector": "文件选择器",
@ -48,11 +57,14 @@
"GetCode": "获取要插入的代码",
"GoToRoom": "前往房间",
"Header": "页眉",
"HeaderDescription": "您可以在移动版本中禁用标题以限制对{{productName}}部分的访问(就像在桌面版本中禁用左侧菜单一样)。",
"HtmlCodeDescription": "使用 <script> 标签嵌入{{productName}}或其部分。复制以下 HTML 代码并将其插入到您的 HTML 文件中。",
"InitializeSDK": "在建议的模式中选择一项,或使用“自定义”手动配置所有参数。",
"InLeftPanel": "在左侧面板中",
"InterfaceElements": "界面元素",
"ItemsCount": "一页上的项目数",
"ItemsCountDescription": "可指定一页上显示的文件/文件夹的数量,以及指定从哪一页开始显示",
"JavaScriptCodeDescription": "使用 JavaScript 嵌入{{productName}}或其部分。复制以下 JavaScript 代码。",
"JavascriptSdk": "Javascript SDK",
"LimitByTime": "受时间段限制",
"LinkSetDescription": "此链接受 {{parameter}} 保护。如要配置链接,",
@ -66,8 +78,10 @@
"MenuDescription": "如果用户不需要进入其他板块,您可以关闭左侧菜单。",
"MobileOnly": "仅移动设备",
"Page": "显示页面(页数)",
"PortalDescription": "嵌入整个{{productName}}以允许用户与所有房间、文件和设置进行交互。",
"PublicRoomDescription": "嵌入公共房间,让用户无需注册即可查看公共房间中的所有文档。",
"RightPanelCollapsed": "右侧面板已收起",
"RoomFilter": "房间过滤器",
"RoomOrFolder": "房间或文件夹",
"RoomOrFolderDescription": "可选择要显示的板块、房间或文件夹",
"RoomPreview": "房间预览",
@ -76,11 +90,15 @@
"RoomTypeDisplay": "房间类型显示",
"Rotate": "旋转",
"Scale": "缩放",
"SDKDescription": "JavaScript SDK 允许您将整个{{productName}}或其部分嵌入到您的 Web 界面中。选择具有预定义参数的现成模式或自定义模式以手动配置。要了解有关 SDK 的更多信息,请参阅",
"SearchBlock": "搜索板块",
"SearchByNameEmail": "按名称或电子邮件搜索",
"SearchFilterAndSort": "搜索、筛选和排序",
"SearchTerm": "搜索词",
"SelectButtonText": "选择按钮文本",
"SelectImage": "选择图片",
"SelectModeEmbedding": "选择嵌入{{productName}}的模式",
"SelectToPortal": "选择{{productName}}",
"SelectTypes": "选择类型",
"SetItUp": "设置",
"SettingUpColumns": "设置列",

View File

@ -1 +1,74 @@
{}
{
"LdapAddCertificateToStoreConfirmation": "是否要将此证书添加到证书存储区并继续导入用户?",
"LdapAdvancedSettings": "高级设置",
"LdapAdvancedSettingsTooltip": "选择要与 LDAP 服务器同步的用户属性。",
"LdapAttributeMapping": "属性映射",
"LdapAuthenticationTooltip": "如果当前 Windows 用户无权从 LDAP 服务器/Active Directory 读取,请启用此选项,并输入具有读取权限的其他用户的凭据。",
"LdapAutoSyncToggle": "自动同步",
"LdapAutoSyncToggleDescription": "同步将允许从门户上传所有数据并在更改设置后更新新数据。每次门户中有新用户数据时都将进行同步。",
"LdapAvatar": "个人资料照片",
"LdapCertificateConfirm": "确认证书",
"LdapDisclaimer": "请记住:门户用户电子邮件将从“邮件属性”设置中获取。如果缺少,则将以以下方式形成:“登录属性 + @ + LDAP 域”。如果不存在这样的电子邮件,用户将不会收到任何门户通知。",
"LdapEnableSSL": "启用 SSL",
"LdapEnableSSLTooltip": "您可以使用安全套接字层SSL使 LDAP 流量保密且安全",
"LdapEnableStartTls": "启用 StartTLS",
"LdapEnableStartTlsTooltip": "StartTLS 提供了一种将纯文本连接升级为加密TLS 或 SSL连接的方法而不是使用单独的端口进行加密通信。",
"LdapFirstName": "名字",
"LdapGroupAttribute": "组属性",
"LdapGroupAttributeTooltip": "输入组对象属性,该属性指定此组包含哪些用户。",
"LdapGroupDN": "组 DN",
"LdapGroupDNTooltip": "输入包含要添加的组的目录的可分辨名称。",
"LdapGroupFilter": "组过滤器",
"LdapGroupFilterTooltip": "使用搜索 LDAP 过滤器选择要导入的组。请注意,只会添加来自这些组的用户。",
"LdapGroupMembership": "组成员资格",
"LdapGroupMembershipTooltip": "如果您想将 LDAP 服务器/Active Directory 中的组添加到{{productName}}帐户,请启用此选项。请注意,只会添加属于这些组的用户。",
"LdapGroupNameAttribute": "组名属性",
"LdapGroupNameAttributeTooltip": "请指定与组名对应的对象属性。",
"LdapGroupUserAttributeTooltip": "输入用于确定此用户是否为组成员的用户对象属性。",
"LdapIntro": "LDAP 是一种从 LDAP 服务器导入用户和组以及使用存储在 LDAP 服务器上的登录名/密码在门户上提供用户身份验证的方法。保存设置后将立即导入用户。稍后添加的用户将在门户上的第一次身份验证期间导入。",
"LdapLoginAttribute": "登录属性",
"LdapLoginAttributeTooltip": "输入与用户登录相对应的对象属性。",
"LdapLoginTooltip": "请指定具有 LDAP 服务器/Active Directory 读取访问权限的登录用户。",
"LdapMail": "邮件",
"LdapMobileSettingsDescription": "使用此选项为您的用户提供品牌体验。这些设置将对您的所有门户有效。",
"LdapMobileSyncDescription": "指定您的公司信息,添加外部资源链接以及在线办公界面中显示的电子邮件地址。",
"LdapNextSync": "下次同步",
"LdapPasswordTooltip": "输入具有从 LDAP 服务器/Active Directory 读取数据的访问权限的用户的密码。",
"LdapPortNumber": "端口号",
"LdapPortNumberTooltip": "输入您的 LDAP 服务器/Active Directory 的端口号。",
"LdapQuota": "用户配额",
"LdapSecondName": "第二个名字",
"LdapSendWelcomeLetter": "发送欢迎信",
"LdapSendWelcomeLetterTooltip": "如果选中,所有新用户都将收到欢迎信。仅当邮件属性映射到 LDAP 时可用。",
"LdapServer": "服务器",
"LdapServerTooltip": "输入不带端口号的 LDAP 服务器 URL例如LDAP://mycompany.com。",
"LdapSettings": "LDAP 设置",
"LdapSettingsCertCnNoMatch": "证书名称与主机名不匹配",
"LdapSettingsCertExpired": "证书已过期",
"LdapSettingsCertIssuerChaining": "未提供证书颁发者链",
"LdapSettingsCertMalformed": "证书格式错误",
"LdapSettingsCertUnrecognizedError": "无法识别的错误",
"LdapSettingsCertUntrustedCa": "颁发证书的证书颁发机构不受信任",
"LdapSettingsCertUntrustedRoot": "颁发证书的根证书颁发机构不受信任",
"LdapSettingsIssuerName": "颁发者名称",
"LdapSettingsSerialNumber": "序列号",
"LdapSettingsSubjectName": "主题名称",
"LdapSettingsUniqueHash": "唯一哈希",
"LdapSettingsValidFrom": "有效期自",
"LdapSettingsValidUntil": "有效期至",
"LdapSyncButton": "同步用户",
"LdapSyncCronTitle": "您可以在此处设置自动同步 LDAP 用户的频率",
"LdapSyncDescription": "同步 LDAP 数据是一种在门户和 LDAP 服务器之间同步数据更改的方法。启用“自动同步”选项并设置自动更新信息的时间段。",
"LdapSyncTitle": "同步 LDAP 数据",
"LdapToggle": "LDAP 身份验证",
"LdapToggleDescription": "如果您想自动将 LDAP 服务器/Active Directory 中的用户添加到{{productName}},请启用此选项。添加的用户将能够使用其 LDAP 服务器/Active Directory 凭据进行授权。{{productName}}不会在本地保存用户密码,并将通过向 LDAP 服务器/Active Directory 发送登录名和密码对用户进行身份验证。",
"LdapUserAttribute": "用户属性",
"LdapUserDN": "用户 DN",
"LdapUserDNTooltip": "输入包含要添加的用户的目录的专有名称。",
"LdapUserFilter": "用户过滤器",
"LdapUserFilterTooltip": "使用搜索 LDAP 过滤器选择必须导入的用户。",
"LdapUserQuotaTooltip": "要为此用户设置存储配额,请在 LDAP 目录中为此属性输入一个整数值。它将以字节为单位显示配额值。此属性仅在首次设置期间应用,可以在“帐户”部分手动更改。",
"LdapUsersType": "用户类型",
"LdapUsersTypeInfo": "用户只能访问管理员邀请他们加入的房间,不能创建自己的房间、文件夹或文件。选择下面的其他类型以提供更多权限。否则,您可以在“帐户”部分手动更改类型。",
"LdapUserTypeTooltip": "所有用户都将使用所选类型添加到{{productName}}。"
}

View File

@ -1,14 +1,19 @@
{
"ClickHere": "点击此处",
"ConfirmEmailDescription": "使用激活邮件中提供的链接。没有收到包含激活链接的邮件?",
"ConfirmEmailHeader": "请激活您的电子邮件 ({{ email }}) 以访问{{productName}}功能。",
"PersonalUserQuotaAdminsDescription": "如要上传和创建新文件和文件夹,请释放磁盘空间,或在<1>存储空间管理设置</1>中管理每位用户的配额。",
"PersonalUserQuotaDescription": "如要上传和创建新文件和文件夹,请释放磁盘空间,或联系管理员增加存储空间配额。",
"RequestActivation": "请求再次激活",
"RoomQuotaDescription": "您可以存档不必要的房间或<1>{{clickHere}}</1>为您的{{productName}}找到更合适的定价计划。",
"RoomQuotaHeader": "房间数量即将超出限制:{{currentValue}}/{{maxValue}}",
"StorageAndRoomHeader": "存储和房间的限制即将被超过。",
"StorageAndUserHeader": "存储和管理员/高级用户的数量限制即将被超过。",
"StorageQuotaDescription": "您可以删除不必要的文件或 <1>{{clickHere}}</1>为您的{{productName}}找到更合适的定价计划。",
"StorageQuotaExceeded": "超出存储空间配额",
"StorageQuotaHeader": "存储空间数量即将超出限制:{{currentValue}}/{{maxValue}}",
"StorageQuotaUserDescription": "您可以删除不必要的文件以释放磁盘空间。",
"TenantCustomQuotaDescription": "您可以在<1>存储空间管理设置</1>中删除不必要的文件,或更改配额。",
"UserQuotaDescription": "<1>{{clickHere}}</1>为您的{{productName}}找到更好的定价计划。",
"UserQuotaHeader": "管理员/高级用户的数量限制即将被超过。 {{currentValue}} / {{maxValue}}"
}

View File

@ -1,9 +1,13 @@
{
"ActionsWithFilesDescription": "徽章将通知您有关上传、创建和更改文件的行动。",
"Badges": "弹窗",
"DailyFeed": "每日{{productName}}信息",
"DailyFeedDescription": "在每日摘要中阅读来自{{productName}}的新闻和事件。",
"ManageNotifications": "管理",
"Notifications": "消息通知",
"RoomsActions": "房间文件操作",
"RoomsActivity": "房间活动",
"RoomsActivityDescription": "每小时消息通知。随时了解有关房间活动的最新动态。"
"RoomsActivityDescription": "每小时消息通知。随时了解有关房间活动的最新动态。",
"UsefulTips": "有用的{{productName}}提示",
"UsefulTipsDescription": "获取有关{{productName}}的有用指南"
}

View File

@ -1 +1,7 @@
{}
{
"PDFFormDialogTitle": "随时可填写的 PDF 表单",
"PDFFormEditDialogDescription": "您想切换到表单编辑模式吗?请注意,表单将不再可供填写,编辑后您需要再次单击“开始填写”按钮才能填写。",
"PDFFormEditDialogTitle": "表单编辑",
"PDFFormIsReadyToast": "PDF 表单 <1>{{filename}}}</1> 已准备好填写。",
"PDFFormSuccessfullyCreatedDescription": "您的 PDF 表单已准备好填写。复制公共链接以开始表单填写过程或邀请其他用户加入此房间。"
}

View File

@ -1,4 +1,6 @@
{
"AccessingProblem": "如果您是现有用户并且在访问此空间时遇到问题,请联系管理员。",
"AdministratorDescription": "{{productName}}配置、房间创建和管理、在{{productName}}和虚拟房间中邀请和管理用户的能力、管理访问权限的能力。",
"Benefits": "优势",
"BusinessExpired": "您的{{planName}}版本已于{{date}}过期",
"BusinessFinalDateInfo": "订阅将于 {{finalDate}} 自动按照更新后的定价和规格续期。您可在 Stripe 客户门户中取消或更改计费信息。",
@ -13,10 +15,16 @@
"DelayedPayment": "{{planName}}版本延迟付款日期{{date}}",
"DowngradeNow": "立即降级",
"ErrorNotification": "更新计费方案失败。请稍后重试或联系销售部门。",
"GracePeriodActivatedDescription": "在宽限期内,管理员无法创建新房间和添加新用户。宽限期截止后,{{productName}}将不可用,直到付款完成。",
"GracePeriodActivatedInfo": "宽限期将于 <1>{{fromDate}} 至 {{byDate}}</1> 间生效(剩余天数:{{delayDaysCount}})。",
"InvalidEmailWithActiveSubscription": "您的订阅仍然有效,但我们建议您选择一位可以访问{{productName}}中订阅设置的新付款人。",
"InvalidEmailWithActiveSubscriptionForAdmin": "您的订阅仍然有效,但我们建议您联系{{productName}}所有者以选择新的付款人。",
"InvalidEmailWithoutActiveSubscription": "我们建议您选择一位可以访问{{productName}}中订阅设置的新付款人。",
"InvalidEmailWithoutActiveSubscriptionByAdmin": "我们建议您联系{{productName}}所有者以选择新的付款人。",
"ManagerTypesDescription": "管理员账户类型及其权限",
"Pay": "付款",
"Payer": "付款者",
"PayerDescription": "此用户可以访问付款详情,并且是唯一可以调整配额和付款的用户。{{productName}}所有者以及付款经理本人可以使用 Stripe 客户门户重新分配付款经理角色。",
"PaymentOverdue": "无法添加新用户。",
"PriceCalculation": "计算价格",
"RenewSubscription": "将订阅更新至{{planName}}版本",

View File

@ -7,16 +7,19 @@
"ActivateRenewDescr": "要获取您的个人续订条款,请联系您的专属经理或给我们发送邮件至<1>{{email}}</1>",
"ActivateRenewSubscriptionHeader": "续订企业版",
"ActivateSwithToProHeader": "切换到完整的企业版",
"ActivateTariffDescr": "您正在使用 {{organizationName}} {{productName}}企业版。",
"ActivateTariffEnterpriseExpiration": "您的订阅于{{date}}到期。",
"ActivateTariffEnterpriseTrialExpiration": "您的试用期在{{date}}到期。",
"ActivateToProBannerHeaderTrial": "购买完整的企业版后可以获得:",
"ActivateUploadDescr": "要激活您的许可证,请在下方上传许可证并单击“激活”。",
"FreeDaysLeft": "剩余{{count}}天可免费使用",
"UpgradeToProBannerHeader": "免费使用企业级办公套件 30 天",
"UpgradeToProBannerInformationAboutShort": "在<1>官方网站</1>上了解更多有关企业版的信息",
"UpgradeToProBannerInformationDemo": "<1>点击这里</1>申请演示",
"UpgradeToProBannerInformationPurchase": "通过邮箱 <1>{{email}}</1> 获得销售团队的咨询",
"UpgradeToProBannerInformationSupport": "获取技术帮助 <1>{{helpUrl}}</1>",
"UpgradeToProBannerInstructionDescr": "使用官方文档进行升级:",
"UpgradeToProBannerInstructionHeader": "要访问专业功能,请开始 {{organizationName}} 企业版的 30 天免费试用。",
"UpgradeToProBannerInstructionItemDocker": "Docker 指南。",
"UpgradeToProBannerInstructionItemLinux": "Linux 指南。",
"UpgradeToProBannerInstructionItemWindows": "Windows 指南。",
@ -25,6 +28,7 @@
"UpgradeToProBannerItemLicenseDescr": "+ 1年的功能和安全更新订阅。",
"UpgradeToProBannerItemLicenseHeader": "终身许可。",
"UpgradeToProBannerItemMobileDescr": "在移动浏览器中编辑文档、电子表格和演示文稿。",
"UpgradeToProBannerItemMobileHeader": "移动编辑。",
"UpgradeToProBannerItemScalabilityDescr": "任何规模的团队都可以易于编辑和协作文档。",
"UpgradeToProBannerItemScalabilityHeader": "可扩展性和集群。",
"UpgradeToProBannerItemSupportDescr": "获得快速的专业帮助,解决你的任何问题",

View File

@ -10,14 +10,18 @@
"EnableUserButton": "启用",
"IndividualRights": "房间内的个人权限",
"InviteLinkTitle": "邀请链接",
"LDAPAccountTooltip": "此用户帐户从 LDAP 加载。如果您需要更改用户名和电子邮件地址,或禁用用户,请参阅 LDAP 目录。",
"LDAPGroupTooltip": "此组从 LDAP 加载。如果您需要重命名、添加或删除用户,请参阅 LDAP 目录。",
"NameChangeButton": "更改名称",
"PasswordChangeButton": "更改密码",
"PendingInviteTitle": "待处理的邀请",
"PendingTitle": "待定",
"PeopleCount": "人数:{{count}}",
"RemoveData": "删除个人数据",
"ResetAuth": "重置身份验证",
"SearchByGroupMembers": "按群组成员搜索",
"SendInviteAgain": "再次发送邀请",
"SSOAccountTooltip": "此用户帐户从 SSO 加载。如果您需要更改用户名和电子邮件地址,请参阅 SSO 服务器。",
"StandardLogin": "标准登录",
"SuccessChangeUserStatus": "用户状态已成功变更",
"SuccessDeleteGroup": "群组删除成功",

View File

@ -1 +1,4 @@
{}
{
"AccessingProblem": "如果您在访问此{{productName}}时遇到问题,请联系管理员。",
"ContactAdministrator": "联系{{productName}}管理员"
}

View File

@ -1 +1,4 @@
{}
{
"PortalRestoring": "{{productName}}正在恢复",
"PreparationPortalDescription": "恢复过程结束后,您将自动重定向到您的{{productName}}。"
}

View File

@ -1,5 +1,6 @@
{
"ActiveSessions": "活动会话",
"AutoDeleteTitle": "所有超过 60 天的会话将被自动删除。",
"ChangeEmailSuccess": "邮箱已成功更改",
"ChangePasswordAfterLoggingOut": "登出后变更密码",
"ConnectSocialNetworks": "连接您的社交媒体",
@ -27,5 +28,6 @@
"SuccessLogout": "活动连接已登出:{{platform}}{{browser}}",
"SystemTheme": "使用系统主题",
"SystemThemeDescription": "根据系统状态切换浅色和深色主题。",
"TerminateAllSessions": "终止除当前会话之外的所有会话",
"TwoFactorDescription": "管理员为所有用户启用了通过代码生成应用进行的双因素身份认证功能。"
}

View File

@ -1,21 +1,26 @@
{
"AboutDataImport": "数据导入包括几个步骤:数据上传、解析、导入配置和导入。您的备份文件将存储在 {{organizationName}}{{productName}}服务器中 24 小时,然后会自动删除。",
"AccentColor": "强调",
"AccessRightsAccessToProduct": "对于{{product}}的访问权限已授予",
"AccessRightsAllUsers": "所有{{users}}",
"AccessRightsChangeOwnerConfirmText": "通过邮件确认后将应用变更。",
"AccessRightsProductUsersCan": "{{category}}用户可",
"AccessRightsUsersFromList": "列表中的{{users}}",
"AccountAlreadyExists": "帐户已存在",
"AccountsWithoutEmails": "我们发现 <1>{{users}} 位用户</1>没有电子邮件。您可以填写他们的电子邮件,或在不执行此操作的情况下继续。",
"AccountsWithoutEmailsNextStep": "我们发现 <1>{{users}} 位用户</1>没有电子邮件。您可以在下一步中将必要数据添加到他们的账号中。",
"AddAllowedIP": "添加允许的 IP 地址",
"AddEmails": "将电子邮件添加至不完整的账号",
"AddEmailsDescription": "检查要导入 {{organizationName}}{{productName}}的未导入用户列表。",
"AddEmailsWarning": "您没有拥有电子邮件的用户。请继续执行下一步添加。",
"AdditionalResources": "额外资源",
"AdditionalResourcesDescription": "选择是否要在{{productName}}菜单中显示指向其他资源的链接。",
"AdditionalResourcesSubtitle": "为用户配置显示有用资源的链接。",
"AddTrustedDomain": "添加受信任的域名",
"Admins": "管理员",
"AdminsMessage": "管理员消息设置",
"AdminsMessageMobileDescription": "您可通过“管理员留言设置”联系门户管理员",
"AdminsMessageSettingDescription": "启用此选项可在登录页面上显示{{productName}}管理员联系表。",
"AllDomains": "任意域",
"AmazonBucketTip": "输入您想存储备份的亚马逊 S3 存储桶唯一名称。",
"AmazonCSE": "客户端加密",
@ -26,11 +31,15 @@
"AmazonSSE": "服务器端加密",
"AmazonSSETip": "将此对象存储于 S3 中时使用的服务器端加密算法。",
"Api": "API",
"ApiPageDescription": "基于 {{organizationName}}{{productName}}创建您自己的生产力平台,并与团队、客户和合作伙伴协作处理文档。",
"ApiPageHeader": "建立您自己的协作平台",
"Appearance": "外观",
"AuditSubheader": "此子部分允许您浏览用户对{{productName}}中的实体(房间、机会、文件等)所做的最新更改(创建、修改、删除等)列表。",
"AuditTrailNav": "审计追踪",
"AutoBackup": "自动备份",
"AutoBackupDescription": "自动备份选项用于自动执行{{productName}}数据备份过程,以便稍后将其恢复到本地服务器。",
"AutoSavePeriod": "自动保存期间",
"AutoSavePeriodHelp": "下面显示的时间对应于{{productName}}中设置的时区。",
"Backup": "备份",
"BackupCreatedError": "遇到错误。请联系您的管理员。",
"BackupCreatedSuccess": "备份副本已成功创建。",
@ -42,7 +51,10 @@
"BackupListWarningText": "若您从列表中删除任何项目,其相应的文件也将被删除。此操作无法撤消。若想删除所有文件,请使用以下链接:",
"BlockingTime": "锁定时间(秒)",
"Branding": "品牌",
"BrandingSectionDescription": "指定您的公司信息,添加{{productName}}界面中显示的外部资源链接和电子邮件地址。",
"BrandingSubtitle": "为用户提供更好的品牌体验",
"BreakpointMobileWarningText": "此部分在移动版本中不可用",
"BreakpointMobileWarningTextPrompt": "请使用桌面或平板电脑访问<1>{{sectionName}}</1>。",
"BreakpointSmallText": "您的窗口太小,无法显示页面的所有内容",
"BreakpointSmallTextPrompt": "请调整窗口大小或启用全屏模式",
"BreakpointWarningText": "该部分仅可在桌面端版本中使用",
@ -61,6 +73,7 @@
"ChooseBackupFiles": "选择备份文件",
"ClearBackupList": "删除所有备份",
"CloseMenu": "关闭菜单",
"CommonFilesDescription": "对于公共部分中的文件,将创建一个单独的房间(公共房间)。只有{{productName}}管理员才能访问此房间。默认情况下,房间的所有者将是启动导入的用户:{{user}}(您)。",
"CompanyInfoSettings": "公司信息设置",
"CompanyInfoSettingsDescription": "此信息将展示在 <1>{{link}}</1> 窗口中。",
"ConfirmEmailSended": "确认邮件已发送至{{ownerName}}",
@ -74,11 +87,14 @@
"DataBackup": "数据备份",
"DataImport": "数据导入",
"DataImportComplete": "数据导入完成",
"DataImportDescription": "将数据从第三方服务导入 {{organizationName}}{{productName}}。数据导入允许传输数据,例如所有用户、他们的个人和共享文档。",
"DataImportProcessing": "数据导入处理",
"Deactivate": "停用",
"DeactivateOrDeletePortal": "停用或删除空间。",
"DefaultSettings": "默认设置",
"DefineQuotaPerRoom": "设置每个房间的额度",
"DefineQuotaPerUser": "设置每个用户的额度",
"DeletePortal": "删除{{productName}}",
"DeletePortalInfo": "删除空间前,请确保已关闭自动计费。您可在 <1>Stripe 客户门户</1>中查看自动计费状态。",
"DeleteTheme": "删除主题",
"DeleteThemeForever": "永久性删除主题?",
@ -92,6 +108,8 @@
"DocumentService": "文件服务",
"DocumentServiceLocationHeaderHelp": "可通过文档服务支持执行文档编辑的服务器服务,支持将文档文件转换为合适的 OfficeOpen XML 格式。 文档服务位置明确了安装了文档服务的服务器地址。",
"DocumentServiceLocationUrlApi": "文件编辑服务地址",
"DocumentServiceLocationUrlInternal": "来自{{productName}}的请求的文档服务地址",
"DocumentServiceLocationUrlPortal": "来自文档服务的请求的{{productName}}地址",
"DownloadCopy": "下载副本",
"DownloadLog": "下载日志",
"DownloadReportBtnText": "下载报告",
@ -107,17 +125,23 @@
"EnterTime": "输入时间",
"EnterTitle": "请输入标题",
"ErrorMessageBruteForceProtection": "指定的参数超出有效值范围。",
"ErrorOccuredDownloadLog": "数据导入期间发生错误。下载日志以检查它们。",
"ErrorsWereFound": "发现 {{errors}} 个错误",
"ForcePathStyle": "力路风格",
"GroupsDescription": "您在上一步中选择的用户将被导入 {{serviceName}} 中创建的群组。群组会在“账号”板块显示。",
"HexCode": "十六进制代码",
"Import": "导入",
"ImportCompleteDescriptionGoogle": "从 Google 工作区到 {{organizationName}}{{productName}}的数据导入已完成!",
"ImportCompleteDescriptionNextcloud": "从 Nextcloud 工作区到 {{organizationName}}{{productName}}的数据导入已完成!",
"ImportCompleteDescriptionWorkspace": "从 {{organizationName}} 工作区到 {{organizationName}}{{productName}}的数据导入已完成!",
"ImportedUsers": "{{selectedUsers}}/{{importedUsers}} 用户已成功导入。",
"ImportFromGoogle": "从Google Workspace 导入",
"ImportFromNextcloud": "从Nextcloud 导入",
"ImportFromPortal": "从{{organizationName}} 工作区导入",
"ImportProcessingDescription": "正在进行数据迁移。请稍候。",
"ImportSectionDescription": "选择要导入的部分。它们将显示在{{productName}}的相应部分中。",
"IncludedInBusiness": "专业版方案中包括",
"IntegrationRequest": "在 {{organizationName}}{{productName}}中缺少有用的集成或组件?向我们的团队提出请求,我们将进行调查。",
"InviteLetterTooltip": "如果开启,所有新用户都将收到包含授权详细信息的邀请邮件。",
"IPSecurity": "IP 安全性",
"IPSecurityMobileDescription": "可使用 IP 安全性限制特定地址外所有 IP 地址登录门户。",
@ -125,7 +149,9 @@
"IPSecurityWarningHelper": "首先,您需要指定当前的 IP或当前 IP 地址所属的 IP 范围,否则在保存设置后将立即阻止您的空间访问权限。空间所有者将可从任意 IP 地址访问空间。",
"LanguageAndTimeZoneSettingsNavDescription": "语言和时区设置用于更改整个门户的语言以及配置时区,适用于所有门户用户,让门户中所有事件以正确的日期和时间显示。",
"LastUpdate": "上次更新时间:{{date}}",
"LDAP": "LDAP 设置",
"LicenseLimitCounter": "许可限制管理员/高级用户:",
"LicenseLimitDescription": "许可证限制计数器包括:{{productName}}中已存在的帐户和您要导入的新用户。如果您导入已拥有{{productName}}帐户的用户,则不会再次将其计入计数器。您的{{productName}}许可证允许您最多拥有 {{maxLimit}} 个用户。",
"Lifetime": "寿命(分钟)",
"LimitThemesTooltip": "您只能创建 3 个自定义主题。如需创建新的主题,请删除一个之前的主题。",
"LocalFile": "本地文件",
@ -157,14 +183,19 @@
"Path": "路径",
"PersonalFiles": "个人文件",
"PersonalFilesDescription": "用户文件和文档会被导入至“文档” > “文档”。",
"PortalAccess": "{{productName}}访问权限",
"PortalCreatedDate": "门户创建日期:{{date}}",
"PortalDeactivation": "停用{{productName}}",
"PortalDeactivationDescription": "使用此选项以暂时停用您的空间。",
"PortalDeactivationHelper": "如果您希望停用此{{productName}},您的空间及其所有相关信息将被阻止,以便在特定时期内无人可以访问它。为此,请点击停用按钮。确认操作的链接将发送到空间所有者的电子邮件地址。",
"PortalDeletion": "{{productName}}删除",
"PortalDeletionDescription": "使用此选项以永久删除您的空间。",
"PortalDeletionEmailSended": "操作确认链接已发送至 {{ownerEmail}}(空间所有者邮件地址)",
"PortalDeletionHelper": "如果您认为自己不应该使用此空间且希望永久性删除空间,请使用删除按钮提交您的请求。在此提醒,您将无法重新激活空间,或恢复与之相关的任何信息。",
"PortalNameEmpty": "账户名称为空",
"PortalNameIncorrect": "账户名称不正确",
"PortalNameLength": "账户名称的长度必须在{{minLength}}至{{maxLength}}个字符之间",
"PortalRenaming": "{{productName}}重命名",
"PortalRenamingDescriptionText": "更改显示在 {{ domain }} 旁的空间的地址。",
"PortalRenamingLabelText": "协作空间的新名称",
"PortalRenamingModalText": "你将要重命名的门户。你真的要继续吗?",
@ -181,6 +212,9 @@
"RecoveryFileNotSelected": "恢复错误。未选择恢复文件",
"RestoreBackup": "数据恢复",
"RestoreBackupDescription": "设置此选项,从之前保存的备份文件中恢复门户数据。",
"RestoreBackupResetInfoWarningText": "所有当前密码都将被重置。{{productName}}用户将收到一封包含访问恢复链接的电子邮件。",
"RestoreBackupWarningText": "{{productName}}在恢复过程中将不可用。恢复完成后,所选恢复点日期之后所做的所有更改都将丢失。",
"RolesAreSet": "已为选定用户设置角色。",
"RoomsModule": "备份房间",
"RoomsModuleDescription": "您可以为备份专门创建一个房间、选择现有房间、或者将副本保存在{{roomName}}中。",
"SaveToApply": "点击底部的<strong>保存</strong>按钮,使其生效。",
@ -190,14 +224,21 @@
"SelectFileDescriptionWorkspace": "选择 {{organizationName}} 工作区备份文件,开始数据导入。数据上传和分析完成后,系统会自动启动下一步。",
"SelectFileInGZFormat": "选择 .GZ 格式的文件",
"SelectUsers": "选择用户",
"SelectUsersDescriptionGoogle": "从列表中选中要导入 {{organizationName}}{{productName}}的用户。来自 Google 工作区 的用户将不带名字/姓氏导入,而是使用他们的电子邮件名称。导入后可以更改用户的名称。{{organizationName}}{{productName}}中已存在的用户会以绿色突出显示,默认情况下不会选中。",
"SelectUsersDescriptionNextcloud": "从列表中选中要导入 {{organizationName}}{{productName}}的用户。只能选择有电子邮件的用户。 {{organizationName}}{{productName}}中已存在的用户会以绿色突出显示,默认情况下不会选中。",
"SelectUsersDescriptionWorkspace": "从列表中选中要导入 {{organizationName}}{{productName}}的用户。 {{organizationName}}{{productName}}中已存在的用户会以绿色突出显示,默认情况下不会选中。",
"SelectUsersWithEmail": "选择有电子邮件的用户",
"SelectUserTypes": "选择用户类型",
"SelectUserTypesDescription": "为导入的用户选择{{productName}}角色:<1>{{productName}}管理员</1>、<1>房间管理员</1> 或 <1>高级用户</1>。默认情况下,每个用户都选择高级用户角色。导入后,您可以管理角色。",
"SendInviteLetter": "发送邀请邮件",
"SendNotificationAboutRestoring": "向用户发送关于协作空间恢复的通知",
"ServerSideEncryptionMethod": "服务器端加密方法",
"ServiceUrl": "服务Url",
"SessionLifetime": "会话寿命",
"SessionLifetimeMobileDescription": "会话生命周期允许设置{{productName}}用户需要再次输入空间凭据才能访问空间的时间(以分钟为单位)。",
"SessionLifetimeSettingDescription": "调整会话生命周期,可定义自动注销的时间段。保存后,会对所有用户执行注销。",
"SetDefaultRoomQuota": "设置此{{productName}}中房间的默认存储配额。房间管理员稍后可以为每个房间单独调整。",
"SetDefaultUserQuota": "设置此{{productName}}用户的存储配额。用户配额会影响每个用户的文档文件夹的存储限制。",
"SettingPasswordDescription": "配置密码强度设置,强制使用更安全的强密码。",
"SettingPasswordStrengthMobileDescription": "通过“密码强度设置”,确定密码阻止猜测和暴力攻击的有效性。",
"SettingPasswordTittle": "密码强度设置",
@ -211,6 +252,7 @@
"SingleSignOn": "单点登录",
"SMTPSettings": "SMTP设置",
"SMTPSettingsDescription": "需要SMTP设置以设置一个电子邮件账户用于使用您自己的SMTP服务器而非{{organizationName}}使用的SMTP服务器以从从门户发送通知。请填写所有字段然后单击“保存”按钮。您可以使用“发送测试邮件”按钮以检查您输入的所有设置是否正确并照常工作。",
"StatisticDescription": "在这里,您可以查看此{{productName}}中的详细存储使用数据。",
"Statistics": "数据统计",
"StorageManagement": "存储空间管理",
"StoragePeriod": "贮存期",
@ -230,6 +272,7 @@
"ThirdPartyResourceDescription": "备份可以保存到您的第三方账户Dropbox、Box.com、OneDrive或Google Drive。您需要连接到您的第三方账户Dropbox、Box.com、OneDrive或Google Drive然后您才能将备份在第三方账户保存",
"ThirdPartyStorageDescription": "备份文件可以保存在第三方存储中。保存之前,您需要在‘集成’板块连接相应的服务。否则该设置将无法激活。",
"ThirdPartyTitleDescription": "您可使用授权密钥通过协作空间连接第三方服务。使用Fcebook、Google或领英轻松登录添加Dropbox、OneDrive等服务以在文档模块中使用存储于其中的文件。",
"TimeLanguageSettingsDescription": "更改语言和时区设置以调整常见的{{productName}}语言和时间。",
"TimeLanguageSettingsSave": "点击底部的<strong>保存</strong>,使其生效。",
"TimeZone": "时区",
"Top5rooms": "存储空间用量排名前 5 位的房间:",
@ -239,8 +282,10 @@
"TrustedMailMobileDescription": "通过“受信任的邮件域设置”,指定用于用户自注册的邮件服务器。",
"TrustedMailSettingDescription": "通过“配置受信任的邮件域设置”,指定允许用于自注册的邮件服务器。",
"TwoFactorAuth": "双因素身份验证",
"TwoFactorAuthEnableDescription": "启用双因素身份验证,为用户提供更安全的{{productName}}访问。",
"TwoFactorAuthMobileDescription": "双因素身份验证是一种更安全的方式,用户用户进入门户。输入凭据之后,用户必须输入首次登录门户时指定的号码收到的短信中的代码,或身份验证应用中的代码。",
"TwoFactorAuthSave": "点击下方的<strong>保存</strong>按钮,使其生效。",
"TypesAndPrivileges": "<1>管理员帐户类型及其权限</1> <br> <br> <2>{{productName}}管理员</2> <br>{{productName}}配置、房间创建和管理、邀请和管理{{productName}}和虚拟房间中的用户的能力、管理访问权限的能力。<br> <br> <3>房间管理员</3> <br> 房间管理和存档、用户邀请和管理。可以将多个管理员分配到一个房间。<br> <br> <4>高级用户</4> <br> 高级用户可以在房间中创建和编辑文件,但不能创建房间、管理用户或访问设置。",
"UnsavedChangesBody": "如果您现在关闭链接设置菜单,您所做的更改可能不会被保存。",
"UnsupportedFilesDescription": "不支持某些备份文件。您可以点击“检查不支持的文件”,下载不支持的项目列表",
"UnsupportedFilesWithUploadDesc": "不支持某些备份文件。您可以点击“检查不支持的文件”下载不支持的项目列表,或点击“上传到服务器”直接继续上传。",
@ -252,6 +297,8 @@
"UsedStorage": "已使用:{{size}}",
"UseHttp": "使用Http",
"UserAgreement": "我确认并继续",
"UserLimitExceeded": "超出用户限制。要继续下一步,请调整用户数量或增加{{productName}}用户限制。",
"UsersAreRegistered": "您选择了在{{productName}}中注册的用户,并且已设置角色。请继续下一步或返回以选择更多用户。",
"UsersSectionDescription": "“用户”部分包括您在上一步中选择的用户。默认情况下,它始终处于启用状态,无法取消选择。",
"UseSpecialChar": "必须包含特殊字符",
"UseUpperCase": "必须包含大写字母",

View File

@ -48,6 +48,7 @@
"SPEntityId": "SP 实体 ID元数据 XML 链接)",
"SPEntityIdTooltip": "克由身份供应商下载和使用以明确识别 SP 的服务供应商 XML URL 地址",
"SpMetadata": "{{organizationName}} SP 元数据",
"SpMetadataDescription": "访问服务提供商元数据以将 {{organizationName}}{{productName}}添加为您的 IdP 帐户中的受信任服务提供商。",
"spSignExitRequest": "签署登出请求",
"spSigningAlgorithm": "签名算法",
"spSignResponseRequest": "签署登出响应",

View File

@ -21,7 +21,6 @@
"FolderTitleWebDav": "WebDAV目录",
"FolderTitleYandex": "Yandex目录",
"FormTemplates": "表单模板",
"LinkCopySuccess": "链接已复制到剪贴板中",
"LinkHasExpiredAndHasBeenDisabled": "此链接过期,已被禁用",
"LinkValidTime": "该链接仅在{{days_count}}天内有效。",
"NewForm": "PDF 表单",
@ -34,6 +33,7 @@
"RoleEditorDescription": "现有文件操作:查看、编辑、表单填写、审阅、评论。",
"RoleFormFiller": "可填写表单",
"RoleFormFillerDescription": "现有文件操作:查看、表单填写、审阅、评论。",
"RolePortalAdminDescription": "{{productName}}管理员可以访问{{productName}}设置、管理和存档房间、邀请新用户并分配其级别以下的角色。所有管理员都可以访问个人部分。",
"RolePowerUserDescription": "高级用户可以在房间里创建和编辑文件,但不能创建房间,管理用户,或访问设置。",
"RoleReviewer": "可审阅",
"RoleReviewerDescription": "现有文件操作:查看、审阅、评论。",

View File

@ -1,5 +1,6 @@
{
"DeletePlugin": "移除插件",
"DeletePluginDescription": "此插件将不再可供{{productName}}用户使用。您确定您要继续吗?",
"DeletePluginTitle": "移除插件?",
"ExpandFunctionality": "使用插件SDK扩展功能",
"GoToRepo": "转到仓库",
@ -9,5 +10,7 @@
"NotNeedSettings": "无需输入设置",
"PluginSamples": "插件示例",
"PluginSDK": "插件SDK",
"PluginSDKInstruction": "单击该按钮了解如何创建您自己的插件。"
"PluginSDKDescription": "使用插件 SDK您可以扩展{{productName}}功能、连接第三方服务或增强现有用户体验。您可以在此处找到 GitHub 上提供的带有代码源的插件示例。",
"PluginSDKInstruction": "单击该按钮了解如何创建您自己的插件。",
"UploadDescription": "您可以添加插件以使用额外功能扩展{{productName}}的功能。单击“上传插件”或将文件拖放到 ZIP 存档中。"
}

View File

@ -46,6 +46,7 @@
"URL": "URL",
"ViewRawPayload": "查看原始负载",
"WebhookCreated": "Webhook 已被创建",
"WebhookCreationHint": "此 webhook 将分配给{{productName}}中的所有事件",
"WebhookDetails": "Webhook 详细信息",
"WebhookEditedSuccessfully": "Webhook 配置编辑成功",
"WebhookHistory": "Webhook 历史",
@ -53,5 +54,6 @@
"WebhookRedilivered": "Webhook 已被重新传递",
"WebhookRemoved": "Webhook 已被移除",
"Webhooks": "Webhook",
"WebhooksGuide": "Webhook 指南"
"WebhooksGuide": "Webhook 指南",
"WebhooksInfo": "使用 webhook 根据 {{organizationName}}{{productName}}中的各种事件在您正在使用的任何应用程序或网站端执行自定义操作。\n在这里您可以创建和管理所有 webhook、配置它们并浏览每个 webhook 的历史记录以审核其性能。"
}

View File

@ -1,4 +1,5 @@
{
"Desc": "请设置{{productName}}注册数据。",
"ErrorEmail": "无效邮件地址",
"ErrorInitWizard": "该服务目前不可用,请稍后重试。",
"ErrorInitWizardButton": "再试一次",
@ -9,5 +10,6 @@
"License": "接受条款:",
"LicenseLink": "许可协议",
"PlaceholderLicense": "您的许可文件",
"Timezone": "时区:"
"Timezone": "时区:",
"WelcomeTitle": "欢迎使用{{productName}}"
}

View File

@ -68,6 +68,7 @@ const CreateEvent = ({
setPortalTariff,
withoutDialog,
preview,
toForm,
publicRoomKey,
actionEdit,
openOnNewPage,
@ -176,6 +177,8 @@ const CreateEvent = ({
searchParams.append("action", "edit");
}
if (toForm) searchParams.append("toForm", "true");
if (publicRoomKey) {
searchParams.append("share", publicRoomKey);
}

View File

@ -50,6 +50,7 @@ const GlobalEvents = ({ enablePlugins, eventListenerItemsList }) => {
templateId: null,
fromTemplate: null,
onClose: null,
toForm: false,
});
const [renameDialogProps, setRenameDialogProps] = useState({
@ -116,6 +117,7 @@ const GlobalEvents = ({ enablePlugins, eventListenerItemsList }) => {
preview: payload.preview ?? false,
actionEdit: payload.edit ?? false,
openEditor: payload.openEditor ?? true,
toForm: payload.toForm ?? false,
onClose: () => {
setCreateDialogProps({
visible: false,
@ -130,6 +132,7 @@ const GlobalEvents = ({ enablePlugins, eventListenerItemsList }) => {
preview: false,
actionEdit: false,
openEditor: true,
toForm: false,
});
},
});

View File

@ -60,9 +60,14 @@ const PureConnectDialogContainer = (props) => {
saveAfterReconnectOAuth,
setSaveAfterReconnectOAuth,
setThirdPartyAccountsInfo,
connectingStorages,
} = props;
const { title, link, token, provider_id, provider_key, key } = item;
const connectItem = connectingStorages.find(
(el) => el.providerKey === provider_key,
);
const provider = providers.find((el) => el.provider_id === item.provider_id);
const folderTitle = provider ? provider.customer_title : title;
@ -81,11 +86,7 @@ const PureConnectDialogContainer = (props) => {
const [isLoading, setIsLoading] = useState(false);
const isAccount = !!link;
const showUrlField =
provider_key === "SharePoint" ||
key === "SharePoint" ||
(!isConnectDialogReconnect &&
(provider_key === "WebDav" || key === "WebDav"));
const showUrlField = !!connectItem?.requiredConnectionUrl;
const header = isConnectDialogReconnect
? t("Common:ReconnectStorage")
@ -416,6 +417,7 @@ export default inject(
saveThirdParty,
openConnectWindow,
fetchThirdPartyProviders,
connectingStorages,
} = filesSettingsStore.thirdPartyStore;
const { folderFormValidation } = settingsStore;
@ -458,6 +460,7 @@ export default inject(
setSaveAfterReconnectOAuth,
setIsConnectDialogReconnect,
setThirdPartyAccountsInfo,
connectingStorages,
};
},
)(observer(ConnectDialog));

View File

@ -125,10 +125,9 @@ const ExternalLinks = ({
const copyLink = (link) => {
if (link) {
toastr.success(
`${t("Translations:LinkCopySuccess")}. ${t(
"Translations:LinkValidTime",
{ days_count: 7 },
)}`,
`${t("Common:LinkCopySuccess")}. ${t("Translations:LinkValidTime", {
days_count: 7,
})}`,
);
copy(link);
}

View File

@ -323,6 +323,11 @@ class FileRow extends Component {
const onMediaClick = () => this.onMediaClick(item.fileId);
const onFileClick = (url) => {
if (!url) return;
window.open(url, downloadInCurrentTab ? "_self" : "_blank");
};
return (
<>
<StyledFileRow
@ -352,11 +357,14 @@ class FileRow extends Component {
) : (
<div className="upload-panel_file-name">
<Link
onClick={() =>
onFileClick(item.fileInfo ? item.fileInfo.webUrl : "")
}
fontWeight="600"
color={item.error && "#A3A9AE"}
truncate
href={item.fileInfo ? item.fileInfo.webUrl : ""}
target={downloadInCurrentTab ? "_self" : "_blank"}
// href={item.fileInfo ? item.fileInfo.webUrl : ""}
// target={downloadInCurrentTab ? "_self" : "_blank"}
>
{name}
{fileExtension}

View File

@ -61,6 +61,7 @@ newInstance
},
ns: [
"Common",
"ArchiveDialog",
"InfoPanel",
"InviteDialog",

View File

@ -183,7 +183,8 @@ const AboutContent = (props) => {
target="_blank"
enableUserSelect
>
&nbsp;ONLYOFFICE Docs&nbsp;
&nbsp;{t("Common:OrganizationName")}{" "}
{t("Common:ProductEditorsName")}&nbsp;
</ColorTheme>
<Text className="row-el select-el" fontSize="13px" fontWeight="600">
v.

View File

@ -7,6 +7,7 @@ enum FeedAction {
Rename = "rename",
Move = "move",
Copy = "copy",
Revoke = "revoke",
}
enum FeedTarget {
@ -148,10 +149,15 @@ export const feedInfo = [
actionType: `${FeedAction.Rename}`,
},
{
key: "RoomExternalLinkRevoked",
key: "RoomExternalLinkDeleted",
targetType: `${FeedTarget.RoomExternalLink}`,
actionType: `${FeedAction.Delete}`,
},
{
key: "RoomExternalLinkRevoked",
targetType: `${FeedTarget.RoomExternalLink}`,
actionType: `${FeedAction.Revoke}`,
},
//
// USER
{

View File

@ -89,7 +89,7 @@ export const useFeedTranslation = (
components={{ 1: <strong /> }}
/>
);
case "RoomExternalLinkRevoked":
case "RoomExternalLinkDeleted":
return (
<Trans
t={t}
@ -101,6 +101,18 @@ export const useFeedTranslation = (
components={{ 1: <strong /> }}
/>
);
case "RoomExternalLinkRevoked":
return (
<Trans
t={t}
ns="InfoPanel"
i18nKey="RoomExternalLinkRevoked"
values={{
linkTitle: feed.data.title || feed.data.sharedTo?.title,
}}
components={{ 1: <strong /> }}
/>
);
case "RoomCreateUser":
return t("InfoPanel:RoomCreateUser");
case "RoomUpdateAccessForUser":

View File

@ -35,7 +35,13 @@ import EmptyContainer from "../../../../components/EmptyContainer";
import withLoader from "../../../../HOCs/withLoader";
import TableView from "./TableView/TableContainer";
import withHotkeys from "../../../../HOCs/withHotkeys";
import { Consumer, isMobile, isTablet } from "@docspace/shared/utils";
import {
clearEdgeScrollingTimer,
Consumer,
isMobile,
isTablet,
onEdgeScrolling,
} from "@docspace/shared/utils";
import { isElementInViewport } from "@docspace/shared/utils/common";
import { DeviceType } from "@docspace/shared/enums";
@ -197,6 +203,7 @@ const SectionBodyContent = (props) => {
setDragging(true);
}
onEdgeScrolling(e);
setTooltipPosition(e.pageX, e.pageY);
const wrapperElement = document.elementFromPoint(e.clientX, e.clientY);
if (!wrapperElement) {
@ -240,6 +247,7 @@ const SectionBodyContent = (props) => {
};
const onMouseUp = (e) => {
clearEdgeScrollingTimer();
setStartDrag(false);
setTimeout(() => {

View File

@ -375,31 +375,29 @@ const SectionHeaderContent = (props) => {
/>
)}
<Headline type="content" truncate={true}>
<div className="settings-section_header">
<div className="header">
{isMobile() && isServicePage && (
<IconButton
iconName={ArrowPathReactSvgUrl}
size="17"
isFill={true}
onClick={onBackToParent}
className="arrow-button"
/>
)}
{t(header, { organizationName: t("Common:OrganizationName") })}
</div>
{isNeedPaidIcon ? (
<Badge
backgroundColor={theme.isBase ? "#EDC409" : "#A38A1A"}
label={t("Common:Paid")}
fontWeight="700"
className="settings-section_badge"
isPaidBadge={true}
/>
) : (
""
)}
</div>
{isMobile() && isServicePage && (
<IconButton
iconName={ArrowPathReactSvgUrl}
size="17"
isFill={true}
onClick={onBackToParent}
className="arrow-button"
/>
)}
{t(header, {
organizationName: t("Common:OrganizationName"),
})}
{isNeedPaidIcon ? (
<Badge
backgroundColor={theme.isBase ? "#EDC409" : "#A38A1A"}
label={t("Common:Paid")}
fontWeight="700"
className="settings-section_badge"
isPaidBadge={true}
/>
) : (
""
)}
</Headline>
<div className="tariff-bar">
<TariffBar />

View File

@ -74,13 +74,15 @@ const WhiteLabel = (props) => {
resetIsInit,
standalone,
theme,
isWhitelableLoaded,
} = props;
const navigate = useNavigate();
const location = useLocation();
const [isLoadedData, setIsLoadedData] = useState(false);
const [logoTextWhiteLabel, setLogoTextWhiteLabel] = useState("");
const [isSaving, setIsSaving] = useState(false);
const [isEmpty, setIsEmpty] = useState(isWhitelableLoaded && !logoText);
const isMobileView = deviceType === DeviceType.mobile;
@ -122,24 +124,22 @@ const WhiteLabel = (props) => {
};
useEffect(() => {
if (!isWhitelableLoaded) return;
const companyNameFromSessionStorage = getFromSessionStorage("companyName");
if (!companyNameFromSessionStorage) {
setIsEmpty(!logoText);
if (!logoText) return;
setLogoTextWhiteLabel(logoText);
saveToSessionStorage("companyName", logoText);
} else {
setIsEmpty(!companyNameFromSessionStorage);
setLogoTextWhiteLabel(companyNameFromSessionStorage);
saveToSessionStorage("companyName", companyNameFromSessionStorage);
}
}, [logoText]);
useEffect(() => {
if (logoTextWhiteLabel && logoUrlsWhiteLabel.length && !isLoadedData) {
setIsLoadedData(true);
}
}, [isLoadedData, logoTextWhiteLabel, logoUrlsWhiteLabel]);
}, [logoText, isWhitelableLoaded]);
const onResetCompanyName = async () => {
const whlText = await getWhiteLabelLogoText();
@ -150,11 +150,19 @@ const WhiteLabel = (props) => {
const onChangeCompanyName = (e) => {
const value = e.target.value;
setLogoTextWhiteLabel(value);
saveToSessionStorage("companyName", value);
const trimmedValue = value?.trim();
setIsEmpty(!trimmedValue);
saveToSessionStorage("companyName", trimmedValue);
};
const onUseTextAsLogo = () => {
if (isEmpty) {
return;
}
let newLogos = logoUrlsWhiteLabel;
for (let i = 0; i < logoUrlsWhiteLabel.length; i++) {
const options = getLogoOptions(
i,
@ -171,6 +179,7 @@ const WhiteLabel = (props) => {
options.fontSize,
isDocsEditorName ? "#fff" : "#000",
options.alignCenter,
options.isEditor,
);
const logoDark = generateLogo(
options.width,
@ -179,6 +188,7 @@ const WhiteLabel = (props) => {
options.fontSize,
"#fff",
options.alignCenter,
options.isEditor,
);
newLogos[i].path.light = logoLight;
newLogos[i].path.dark = logoDark;
@ -265,7 +275,7 @@ const WhiteLabel = (props) => {
const isEqualText = defaultLogoTextWhiteLabel === logoTextWhiteLabel;
const saveButtonDisabled = isEqualLogo && isEqualText;
return !isLoadedData ? (
return !isWhitelableLoaded ? (
<LoaderWhiteLabel />
) : (
<WhiteLabelWrapper showReminder={!saveButtonDisabled}>
@ -308,6 +318,7 @@ const WhiteLabel = (props) => {
labelText={t("Common:CompanyName")}
isVertical={true}
className="settings_unavailable"
hasError={isEmpty}
>
<TextInput
className="company-name input"
@ -319,6 +330,7 @@ const WhiteLabel = (props) => {
isAutoFocussed={!isMobile}
tabIndex={1}
maxLength={30}
hasError={isEmpty}
/>
<Button
id="btnUseAsLogo"
@ -563,6 +575,7 @@ export default inject(({ settingsStore, common, currentQuotaStore }) => {
defaultLogoTextWhiteLabel,
enableRestoreButton,
resetIsInit,
isWhitelableLoaded,
} = common;
const {
@ -590,5 +603,7 @@ export default inject(({ settingsStore, common, currentQuotaStore }) => {
deviceType,
resetIsInit,
standalone,
isWhitelableLoaded,
};
})(withTranslation(["Settings", "Profile", "Common"])(observer(WhiteLabel)));

View File

@ -183,7 +183,7 @@ const Appearance = (props) => {
useEffect(() => {
getSettings();
setDocumentTitle(t("Appearance"));
setDocumentTitle(t("Common:Appearance"));
}, []);
useEffect(() => {

View File

@ -110,7 +110,7 @@ const Customization = (props) => {
const isLoadedSetting = isLoaded && tReady;
useEffect(() => {
setDocumentTitle(t("Customization"));
setDocumentTitle(t("Settings:Customization"));
return () => {
resetIsInit();

View File

@ -34,6 +34,7 @@ import { RectangleSkeleton } from "@docspace/shared/skeletons";
import GithubLight from "PUBLIC_DIR/images/github.light.react.svg";
import GithubDark from "PUBLIC_DIR/images/github.dark.react.svg";
import { setDocumentTitle } from "SRC_DIR/helpers/utils";
import { StyledContainer } from "./StyledPluginSDK";
@ -48,6 +49,10 @@ const PluginSDK = ({
}) => {
const { t } = useTranslation(["WebPlugins", "VersionHistory", "Common"]);
React.useEffect(() => {
setDocumentTitle(t("WebPlugins:PluginSDK"));
}, []);
const isMobile = currentDeviceType === "mobile";
const icon = !theme.isBase ? <GithubLight /> : <GithubDark />;

View File

@ -38,6 +38,7 @@ import { toastr } from "@docspace/shared/components/toast";
import { SettingsDSConnectSkeleton } from "@docspace/shared/skeletons/settings";
import { DeviceType } from "@docspace/shared/enums";
import { SaveCancelButtons } from "@docspace/shared/components/save-cancel-buttons";
import { setDocumentTitle } from "SRC_DIR/helpers/utils";
const URL_REGEX = /^https?:\/\/[-a-zA-Z0-9@:%._\+~#=]{1,256}\/?$/;
const DNS_PLACEHOLDER = `${window.location.protocol}//<docspace-dns-name>/`;
@ -69,6 +70,7 @@ const DocumentService = ({
const [initInternalUrl, setInitInternalUrl] = useState("");
useEffect(() => {
setDocumentTitle(t("DocumentService"));
setIsLoading(true);
getDocumentServiceLocation()
.then((result) => {

View File

@ -77,7 +77,7 @@ const MetadataUrlField = ({
const onCopyClick = () => {
copy(placeholder);
toastr.success(t("Translations:LinkCopySuccess"));
toastr.success(t("Common:LinkCopySuccess"));
};
return (

View File

@ -157,7 +157,8 @@ const StyledFolderTagSection = styled.div`
width: ${(props) => props.width + "%"};
&:first-of-type {
border-radius: 46px 0px 0px 46px;
border-start-start-radius: 46px;
border-end-start-radius: 46px;
}
`;

View File

@ -34,14 +34,16 @@ export const generateLogo = (
text,
fontSize = 18,
fontColor = "#000",
alignCenter,
alignCenter = false,
isEditor = false,
) => {
const canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
console.log("isEditor", isEditor);
const ctx = canvas.getContext("2d");
const x = alignCenter ? width / 2 : 0;
const x = alignCenter ? width / 2 : isEditor ? 10 : 0;
const y = (height - fontSize) / 2;
ctx.fillStyle = "transparent";
ctx.clearRect(0, 0, width, height);
@ -87,6 +89,8 @@ export const getLogoOptions = (index, text, width, height) => {
text,
width,
height,
alignCenter: false,
isEditor: true,
};
case 4:
return {
@ -94,6 +98,8 @@ export const getLogoOptions = (index, text, width, height) => {
text,
width,
height,
alignCenter: false,
isEditor: true,
};
case 5:
return {

View File

@ -211,6 +211,13 @@ class CommonStore {
this.applyNewLogos(logos);
};
get isWhitelableLoaded() {
return (
this.logoUrlsWhiteLabel.length > 0 &&
this.whiteLabelLogoText !== undefined
);
}
getGreetingSettingsIsDefault = async () => {
const isDefault = await api.settings.getGreetingSettingsIsDefault();
runInAction(() => {

View File

@ -396,7 +396,7 @@ class ContextOptionsStore {
: `${window.location.origin + config.homepage}/filter?folder=${id}`, //TODO: Change url by category
);
toastr.success(t("Translations:LinkCopySuccess"));
toastr.success(t("Common:LinkCopySuccess"));
};
onCopyLink = async (item, t) => {
@ -415,7 +415,7 @@ class ContextOptionsStore {
? await getFolderLink(item.id)
: await getFileLink(item.id);
copyShareLink(itemLink.sharedTo.shareLink);
toastr.success(t("Translations:LinkCopySuccess"));
toastr.success(t("Common:LinkCopySuccess"));
} catch (error) {
toastr.error(error);
}
@ -427,13 +427,13 @@ class ContextOptionsStore {
item.rootFolderType === FolderType.SHARE
) {
copy(item.webUrl);
return toastr.success(t("Translations:LinkCopySuccess"));
return toastr.success(t("Common:LinkCopySuccess"));
}
if (href) {
copy(href);
return toastr.success(t("Translations:LinkCopySuccess"));
return toastr.success(t("Common:LinkCopySuccess"));
}
const { canConvert } = this.filesSettingsStore;
@ -454,7 +454,7 @@ class ContextOptionsStore {
copy(url);
toastr.success(t("Translations:LinkCopySuccess"));
toastr.success(t("Common:LinkCopySuccess"));
};
onOpenEmbeddingSettings = async (item) => {
@ -748,7 +748,7 @@ class ContextOptionsStore {
// label: title,
// onClick: () => {
// copy(shareLink);
// toastr.success(t("Translations:LinkCopySuccess"));
// toastr.success(t("Common:LinkCopySuccess"));
// },
// });
// }
@ -1125,7 +1125,7 @@ class ContextOptionsStore {
icon: TabletLinkReactSvgUrl,
onClick: () => {
copy(window.location.href);
toastr.success(t("Translations:LinkCopySuccess"));
toastr.success(t("Common:LinkCopySuccess"));
},
disabled: this.settingsStore.isFrame,
},

View File

@ -417,6 +417,7 @@ class DialogsStore {
withoutDialog,
preview,
edit: true,
toForm: true,
};
event.payload = payload;

View File

@ -69,7 +69,8 @@ class FilesSettingsStore {
openEditorInSameTab = null;
thumbnails1280x720 = window.ClientConfig?.thumbnails1280x720 || false;
chunkUploadSize = 1024 * 1023; // 1024 * 1023; //~0.999mb
chunkUploadCount = 5;
maxUploadThreadCount = 15;
maxUploadFilesCount = 5;
settingsIsLoaded = false;
@ -122,6 +123,10 @@ class FilesSettingsStore {
this.settingsIsLoaded = isLoaded;
};
get uploadThreadCount() {
return this.maxUploadThreadCount / this.maxUploadFilesCount;
}
get isLoadedSettingsTree() {
return (
this.confirmDelete !== null &&

View File

@ -83,6 +83,7 @@ class ThirdPartyStore {
isOauth: storage.oauth,
oauthHref: storage.redirectUrl,
category: storage.name,
requiredConnectionUrl: storage.requiredConnectionUrl,
}));
};

View File

@ -707,6 +707,14 @@ class UploadDataStore {
};
startUpload = (uploadFiles, folderId, t) => {
const withoutHiddenFiles = Object.values(uploadFiles).filter((f) => {
const isHidden = /(^|\/)\.[^\/\.]/g.test(f.name);
return !isHidden;
});
console.log("startUpload", { withoutHiddenFiles, uploadFiles });
const { canConvert } = this.filesSettingsStore;
const toFolderId = folderId ? folderId : this.selectedFolderStore.id;
@ -728,10 +736,10 @@ class UploadDataStore {
let filesSize = 0;
let convertSize = 0;
const uploadFilesArray = Object.keys(uploadFiles);
const uploadFilesArray = Object.keys(withoutHiddenFiles);
const hasFolder =
uploadFilesArray.findIndex((_, ind) => {
const file = uploadFiles[ind];
const file = withoutHiddenFiles[ind];
const filePath = file.path
? file.path
@ -746,13 +754,13 @@ class UploadDataStore {
if (this.uploaded) {
this.isParallel = false;
} else if (this.isParallel) {
this.tempFiles.push({ uploadFiles, folderId, t });
this.tempFiles.push({ withoutHiddenFiles, folderId, t });
return;
}
}
for (let index of uploadFilesArray) {
const file = uploadFiles[index];
const file = withoutHiddenFiles[index];
const parts = file.name.split(".");
const ext = parts.length > 1 ? "." + parts.pop() : "";
@ -1173,7 +1181,7 @@ class UploadDataStore {
operationId,
toFolderId,
) => {
const { chunkUploadCount: asyncChunkUploadCount } = this.filesSettingsStore;
const { uploadThreadCount } = this.filesSettingsStore;
const length = requestsDataArray.length;
const isThirdPartyFolder = typeof toFolderId === "string";
@ -1204,8 +1212,7 @@ class UploadDataStore {
}
const promise = new Promise((resolve, reject) => {
let i =
length <= asyncChunkUploadCount ? length : asyncChunkUploadCount;
let i = length <= uploadThreadCount ? length : uploadThreadCount;
while (i !== 0) {
this.asyncUpload(
t,
@ -1269,15 +1276,15 @@ class UploadDataStore {
// console.log("IS PARALLEL");
const notUploadedFiles = this.files.filter((f) => !f.inAction);
const { chunkUploadCount } = this.filesSettingsStore;
const { maxUploadFilesCount } = this.filesSettingsStore;
const countFiles =
notUploadedFiles.length >= chunkUploadCount
? chunkUploadCount
notUploadedFiles.length >= maxUploadFilesCount
? maxUploadFilesCount
: notUploadedFiles.length;
for (let i = 0; i < countFiles; i++) {
if (this.currentUploadNumber <= chunkUploadCount) {
if (this.currentUploadNumber <= maxUploadFilesCount) {
const fileIndex = this.files.findIndex(
(f) => f.uniqueId === notUploadedFiles[i].uniqueId,
);

View File

@ -1,7 +1,11 @@
{
"BackToRoom": "Back to room",
"CheckReadyForm": "Check ready form",
"Description": "Your form completed and saved",
"DescriptionForAnonymous": "You submitted the filled PDF form which was assigned a unique number. To check the status, contact the form owner providing the assigned number.",
"DescriptionForRegisteredUser": "The filled PDF form is saved and available to you in the Complete folder. To check the status, contact the form owner providing the assigned number.",
"FillItOutAgain": "Fill it out again",
"FormCompletedSuccessfully": "Form completed successfully",
"FormNumber": "Form number:",
"Manager": "Manager:",
"Title": "The form is completed"

View File

@ -1 +1,8 @@
{}
{
"BackToRoom": "返回房间",
"Description": "您的表单已完成并保存",
"FillItOutAgain": " 再次填写",
"FormNumber": "表单编号:",
"Manager": "管理员:",
"Title": "表单已完成"
}

Some files were not shown because too many files have changed in this diff Show More