using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; using Newtonsoft.Json.Linq; using UnityEngine; using Crowdin.Plugin.Server_API.Helpers; using Crowdin.Plugin.Server_API.Models.StringTranslations; #nullable enable namespace Crowdin.Plugin.Server_API.Services { public class StringTranslationsApiService : BaseApiService { private static string BaseUri => SettingsHelper.GetUri("languages", SettingsHelper.GetProjectId()); private readonly CrowdinHttpClient _httpClient = CrowdinHttpClient.Default; private const int SingleRequestThreshold = 500; private const string PluralContentType = "application/vnd.crowdin.text+plural"; public async Task> ListLanguageTranslations( string languageId, IEnumerable? stringIds = null, int limit = 500, int? branchId = null, CancellationToken ct = default) { if (stringIds is null || stringIds.Count() <= SingleRequestThreshold) { return await ListLanguageTranslations_Request(languageId, stringIds, limit, branchId, ct); } IEnumerable chunks = stringIds .Select((value, index) => new { value, index }) .GroupBy(x => x.index / SingleRequestThreshold) .Select(grouping => grouping.Select(x => x.value).ToArray()); var responseList = new List(); foreach (int[] chunk in chunks) { List partialResponse = await ListLanguageTranslations_Request(languageId, chunk, limit, branchId, ct); responseList.AddRange(partialResponse); } return responseList; } private async Task> ListLanguageTranslations_Request( string languageId, IEnumerable? stringIds, int limit, int? branchId, CancellationToken ct) { var url = $"{BaseUri}/{languageId}/translations"; if (stringIds is not null) { string stringIdsQuery = string.Join(",", stringIds); if (!string.IsNullOrWhiteSpace(stringIdsQuery)) { url += url.Contains('?') ? $"&stringIds={stringIdsQuery}" : $"?stringIds={stringIdsQuery}"; } } if (branchId.HasValue) { url += url.Contains('?') ? $"&branchId={branchId.Value}" : $"?branchId={branchId.Value}"; } try { List rawItems = await _httpClient.ListAllRawAsync(url, limit, ct); var responseList = new List(); foreach (JObject obj in rawItems) { var contentType = obj["contentType"]?.Value(); if (string.IsNullOrWhiteSpace(contentType) || contentType is PluralContentType) { continue; } LanguageTranslation? languageTranslation = CrowdinHttpClient.Deserialize(obj); if (languageTranslation is null) { continue; } responseList.Add(languageTranslation); } return responseList; } catch (CrowdinApiException ex) { // Matches main's behaviour: a failure fetching one language/chunk must not abort // the whole pull - the caller (PullStrings) continues with the remaining // languages and tables instead of failing the entire operation. Debug.LogException(ex); return new List(); } } } }