-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Translations update from Hosted Weblate #2575
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
WalkthroughAdds many new and updated translation entries across multiple locale JSON files (pt_BR, de, it, tr, cs, ru, zh_Hans, hu) and minor JSON punctuation adjustments; no code or control-flow changes. Changes
Sequence Diagram(s)(Changes are translation-only; no control-flow modifications — no sequence diagram provided.) Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
01aabae to
814b102
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (3)
locales/it/translation.json (1)
960-961: Italian wording tweak for natural UIPrefer imperative/concise phrasing.
- "Make cursor time zero": "Rendi il tempo del cursore zero" + "Make cursor time zero": "Azzera il tempo del cursore"locales/tr/translation.json (1)
971-972: Turkish phrasing improvementMore idiomatic for a menu/action label.
- "Make cursor time zero": "İmleç zamanını sıfır yap" + "Make cursor time zero": "İmleç zamanını 0'a ayarla"locales/ru/translation.json (1)
993-994: Russian phrasing improvementUse a clearer action verb and numeral.
- "Make cursor time zero": "Сделать время курсора нулевым" + "Make cursor time zero": "Установить время курсора в 0"
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
locales/cs/translation.json(3 hunks)locales/de/translation.json(41 hunks)locales/hu/translation.json(1 hunks)locales/it/translation.json(1 hunks)locales/pt_BR/translation.json(2 hunks)locales/ru/translation.json(1 hunks)locales/tr/translation.json(1 hunks)locales/zh_Hans/translation.json(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- locales/zh_Hans/translation.json
- locales/hu/translation.json
- locales/cs/translation.json
🔇 Additional comments (3)
locales/pt_BR/translation.json (2)
1-960: JSON structure is valid.The Brazilian Portuguese translation file maintains proper JSON formatting with no syntax errors detected throughout. The file appropriately adds numerous new translation entries and includes the new "Make cursor time zero" key as documented in the PR summary.
264-264: Based on the verification performed, the script output confirms that the placeholder{{example}}used in line 264 oflocales/pt_BR/translation.jsonis consistent across multiple locale files (nb_NO, zh_Hant, zh_Hans, vi, uk). All translation files for the "Please input a valid duration" key use the identical placeholder structure. The translation at line 264 is correct and consistent with the established pattern.locales/de/translation.json (1)
1-1001: JSON structure is valid and translations appear sound.The German translation file is properly formatted JSON with no syntax errors. The numerous changes represent typical translation refinements: improved grammar, corrected terminology (e.g., "HEVC-Dateien" → "HEVC-Videos" at line 5), and enhanced clarity. The new "Make cursor time zero" key at line 1001 is correctly formatted and consistent with other locale files.
locales/it/translation.json
Outdated
| "Video tracks": "Tracce video", | ||
| "Make cursor time zero": "Rendi il tempo del cursore zero" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Sanity-check: key present in all locales and JSON valid
Quick repo scan to ensure every locales/*/translation.json contains the new key and is valid JSON.
🏁 Script executed:
#!/usr/bin/env bash
set -euo pipefail
python - <<'PY'
import json, glob, sys
key = "Make cursor time zero"
missing, errors = [], []
for path in glob.glob("locales/*/translation.json"):
try:
with open(path, encoding="utf-8") as f:
data = json.load(f)
except Exception as e:
errors.append(f"{path}: {e}")
continue
if key not in data:
missing.append(path)
print("JSON errors:" if errors else "No JSON errors.", *errors, sep="\n")
print("Missing key in:" if missing else "All locales contain the key.", *missing, sep="\n")
PYLength of output: 767
Add the new key "Make cursor time zero" to all 26 missing locale files
The sanity check failed: the key exists only in locales/it/translation.json but is missing from all other locale files (ar, es, et, fa, fi, fr, he, id, ja, ko, lt, nb_NO, nl, nn, pl, pt, ro, si, sk, sl, sr, sv, ta, uk, vi, zh_Hant). All these files must be updated with appropriate translations for this key to maintain consistency across supported languages.
🤖 Prompt for AI Agents
In locales/it/translation.json around lines 960-961 the key "Make cursor time
zero" exists only in Italian; add the exact same key "Make cursor time zero"
with an appropriate translated value to each of the missing locale files (ar,
es, et, fa, fi, fr, he, id, ja, ko, lt, nb_NO, nl, nn, pl, pt, ro, si, sk, sl,
sr, sv, ta, uk, vi, zh_Hant) to restore parity—if you don’t have a verified
translation for a language, add the English string as a temporary fallback and
add a TODO comment for later translation, keeping file formatting and ordering
consistent with other keys.
66b2a57 to
856dd11
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (3)
locales/cs/translation.json (1)
1004-1005: Czech phrasing tweak (optional).“Nastavit čas v místě kurzoru jako nulový” works; more idiomatic would be “Nastavit čas v místě kurzoru na nulu”.
- "Make cursor time zero": "Nastavit čas v místě kurzoru jako nulový" + "Make cursor time zero": "Nastavit čas v místě kurzoru na nulu"locales/tr/translation.json (1)
971-987: Minor Turkish wording nits (optional).Prefer noun forms:
- “Setting” → “Ayar”
- “System default” → “Sistem varsayılanı”
Everything else looks solid.
- "Setting": "Ayarlanıyor", + "Setting": "Ayar", - "System default": "Sistem öntanımlı değeri", + "System default": "Sistem varsayılanı",Please confirm UI context for “Setting” is a noun, not a progress state.
locales/pt_BR/translation.json (1)
900-900: pt_BR phrasing tweak for new key (optional).Current is clear; idiomatic alternative:
- "Make cursor time zero": "Tornar zero o tempo do cursor", + "Make cursor time zero": "Zerar o tempo no cursor",
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
locales/cs/translation.json(3 hunks)locales/hu/translation.json(1 hunks)locales/it/translation.json(1 hunks)locales/pt_BR/translation.json(2 hunks)locales/ru/translation.json(1 hunks)locales/tr/translation.json(1 hunks)locales/zh_Hans/translation.json(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
- locales/ru/translation.json
- locales/it/translation.json
- locales/zh_Hans/translation.json
- locales/hu/translation.json
🔇 Additional comments (3)
locales/cs/translation.json (2)
702-702: LGTM (placeholder parity).Text is concise; {{values}} preserved.
924-924: LGTM; consistency with “Ne‑globální”.Wording matches nearby term “Ne‑globální” (Line 920). No placeholder loss.
Please run the placeholder-audit script in my pt_BR comment to verify parity repo-wide.
locales/pt_BR/translation.json (1)
264-264: LGTM (placeholder parity).{{example}} preserved; punctuation OK.
| "Subtitles (SRT)": "Legendas (SRT)", | ||
| "<0>If you're having a problem or question about LosslessCut, please first check the links in the <1>Help</1> menu. If you cannot find any resolution, you may ask a question in <3>GitHub discussions</3> or on <5>Discord.</5></0><1>If you believe that you found a bug in LosslessCut, you may <1>report a bug</1>.</1>": "<0>Se você tiver algum problema ou dúvida sobre o LosslessCut, verifique primeiro os links no menu <1>Ajuda</1>. Se não encontrar nenhuma solução, faça uma pergunta nas <3>Discussões do GitHub</3> ou no <5>Discord.</5></0><1>Se você acredita ter encontrado um bug no LosslessCut, pode <1>relatar um bug</1>.</1>", | ||
| "Adjusting the output FPS and cutting at the same time will cause incorrect cuts. Consider instead doing it in two separate steps.": "Ajustar o FPS de saída e cortar ao mesmo tempo causará cortes incorretos. Considere fazer isso em duas etapas separadas.", | ||
| "At least one codec is not supported by the selected output file format. Try another output format or try to disable one or more tracks.": "Pelo menos um codec não é suportado pelo formato de arquivo de saída selecionado. Tente outro formato de saída ou tente desativar uma ou mais faixas.", | ||
| "At least one resulting file name contains invalid character(s): {{invalidChars}}": "Pelo menos um nome de arquivo resultante contém caracteres inválidos: {{invalidChars}}", | ||
| "At least one resulting file name ends with a whitespace character or a dot, which is not allowed.": "Pelo menos um nome de arquivo resultante termina com um caractere de espaço em branco ou um ponto, o que não é permitido.", | ||
| "Combination is already bound to \"{{alreadyBoundKey}}\". Do you want to replace the existing binding?": "A combinação já está vinculada a \"{{alreadyBoundKey}}\". Deseja substituir a vinculação existente?", | ||
| "Cut at the preceding keyframe (not accurate time.) Equiv to": "Cortar no quadro chave anterior (tempo não preciso). Equivalente a", | ||
| "Divide timeline into a number of segments with an approximate byte size": "Dividir linha do tempo em vários segmentos com um tamanho aproximado de bytes", | ||
| "DV Analyzer Summary.txt": "Resumo do Analisador DV.txt", | ||
| "Enable \"{{filterName}}\" bitstream filter.": "Habilitar filtro de fluxo de bits \"{{filterName}}\".", | ||
| "Enabling this will allow faster playback of the exported file. This makes processing use 3 times as much export I/O, which is negligible for small files but might slow down exporting of large files.": "Habilitar isso permitirá uma reprodução mais rápida do arquivo exportado. Isso faz com que o processamento use 3 vezes mais E/S de exportação, o que é insignificante para arquivos pequenos, mas pode tornar a exportação de arquivos grandes mais lenta.", | ||
| "Enter a JavaScript expression which will be evaluated for each segment. Segments for which the expression evaluates to \"true\" will be selected. <1>View available syntax.</1>": "Insira uma expressão JavaScript que será avaliada para cada segmento. Os segmentos para os quais a expressão for avaliada como \"verdadeiro\" serão selecionados. <1>Veja a sintaxe disponível.</1>", | ||
| "Enter a JavaScript expression which will be evaluated for each selected segment. Returned properties will be edited. <1>View available syntax.</1>": "Insira uma expressão JavaScript que será avaliada para cada segmento selecionado. As propriedades retornadas serão editadas. <1>Veja a sintaxe disponível.</1>", | ||
| "Enter a JavaScript filter expression which will be evaluated for each track of the current file. Tracks for which the expression evaluates to \"true\" will be selected or deselected. You may also the <1></1> keyboard action to run this filter.": "Insira uma expressão de filtro JavaScript que será avaliada para cada faixa do arquivo atual. As faixas para as quais a expressão for avaliada como \"true\" serão selecionadas ou desmarcadas. Você também pode usar a ação de teclado <1></1> para executar este filtro.", | ||
| "Expand segments +5 sec": "Expandir segmentos +5 seg", | ||
| "Exporting whole file without cutting, because there are no segments to export.": "Exportar arquivo inteiro sem cortar, porque não há segmentos para exportar.", | ||
| "Extract frames from current segment as image files": "Extrair quadros do segmento atual como arquivos de imagem", | ||
| "Extract frames from selected segments as image files": "Extrair quadros de segmentos selecionados como arquivos de imagem", | ||
| "Fell back to default output file name": "Retornar ao nome do arquivo de saída padrão", | ||
| "File is not natively supported. Preview playback may be slow and of low quality, but the final export will be lossless. You may convert the file from the menu for a better preview.": "O arquivo não possui suporte nativo. A reprodução da pré-visualização pode ser lenta e de baixa qualidade, mas a exportação final será sem perdas. Você pode converter o arquivo no menu para uma pré-visualização melhor.", | ||
| "Generating full overview waveform, this may take a few minutes.": "Gerando uma forma de onda de visão geral completa, isso pode levar alguns minutos.", | ||
| "Losslessly download a whole media file from the specified URL, mux it into an mkv file and open it in LosslessCut. This can be useful if you need to download a video from a website, e.g. a HLS streaming video. For example in Chrome you can open Developer Tools and view the network traffic, find the playlist (e.g. m3u8) and copy paste its URL here.": "Baixe sem perdas um arquivo de mídia inteiro a partir da URL especificada, multiplexe-o em um arquivo mkv e abra-o no LosslessCut. Isso pode ser útil se você precisar baixar um vídeo de um site, por exemplo, um vídeo de streaming HLS. Por exemplo, no Chrome, você pode abrir as Ferramentas do Desenvolvedor e visualizar o tráfego de rede, encontrar a playlist (por exemplo, m3u8) e copiar e colar o URL aqui.", | ||
| "Make cursor time zero": "Tornar zero o tempo do cursor", | ||
| "Mini-waveform has been enabled. Click again to enable full-screen waveform": "A mini forma de onda foi habilitada. Clique novamente para habilitar a forma de onda em tela cheia", | ||
| "Minimum numeric padded length": "Comprimento mínimo numérico preenchido", | ||
| "Mouse wheel frame seek modifier key": "Tecla modificadora de busca de quadro pela roda do mouse", | ||
| "Mouse wheel keyframe seek modifier key": "Tecla modificadora de busca de quadro-chave pela roda do mouse", | ||
| "Note that this only applies when extracting multiple frames. When \"Frame number\" is selected, frame numbers are relative to the start of the segment (starting from 1).": "Observe que isso só se aplica à extração de vários quadros. Quando \"Número do quadro\" é selecionado, os números dos quadros são relativos ao início do segmento (começando em 1).", | ||
| "OpenTimelineIO": "OpenTimelineIO", | ||
| "Output file name is the same as the source file name. This increases the risk of accidentally overwriting or deleting source files!": "O nome do arquivo de saída é o mesmo do arquivo de origem. Isso aumenta o risco de sobrescrever ou excluir acidentalmente os arquivos de origem!", | ||
| "Output file name template results in duplicate file names (you are trying to export multiple files with the same name). You can fix this for example by adding the \"{{segNumVariable}}\" variable.": "O modelo de nome de arquivo de saída resulta em nomes de arquivo duplicados (você está tentando exportar vários arquivos com o mesmo nome). Você pode corrigir isso, por exemplo, adicionando a variável \"{{segNumVariable}}\".", | ||
| "Overwrite output setting is disabled and some files might have been skipped.": "A configuração de saída de substituição está desabilitada e alguns arquivos podem ter sido ignorados.", | ||
| "Please enter a JavaScript expression.": "Por favor, insira uma expressão JavaScript.", | ||
| "Please enter a number from 1 to {{n}} to be the new order for the current segment": "Insira um número de 1 a {{n}} para ser a nova ordem do segmento atual", | ||
| "Please enter a valid number.": "Por favor, insira um número válido.", | ||
| "Please input a valid size. Example: {{example}}": "Por favor, insira um tamanho válido. Exemplo: {{example}}", | ||
| "Please select a working directory first": "Por favor, seleciona uma pasta de trabalho primeiro", | ||
| "Read all keyframes": "Ler todos os quadros-chave", | ||
| "Reading all keyframes": "Lendo todos os quadros-chave", | ||
| "Remember window size and position": "Lembrar posição e tamanho da janela", | ||
| "Remove current segment cutpoint": "Remover ponto de corte do segmento atual", | ||
| "Remove cutpoint from segment {{segmentNumber}}": "Remover ponto de corte do segmento {{segmentNumber}}", | ||
| "Sanitize file names": "Corrigir nomes de arquivos", | ||
| "Seek one frame": "Buscar um quadro", | ||
| "Seek one key frame": "Buscar um quadro-chave", | ||
| "Segment duration less than 5 seconds": "Duração do segmento menor do que 5 segundos", | ||
| "Segment label (exact)": "Rótulo do segmento (exato)", | ||
| "Segment label (regexp)": "Rótulo do segmento (regexp)", | ||
| "Segment mode: \"{{mode1}}\" will create segments bounding the black sections. \"{{mode2}}\" will create segments that start/stop at the center of each black section.": "Modo de segmento: \"{{mode1}}\" criará segmentos delimitando as seções pretas. \"{{mode2}}\" criará segmentos que começam/param no centro de cada seção preta.", | ||
| "Segment mode: \"{{mode1}}\" will create segments bounding the silent sections. \"{{mode2}}\" will create segments that start/stop at the center of each silent section.": "Modo de segmento: \"{{mode1}}\" criará segmentos delimitando as seções silenciosas. \"{{mode2}}\" criará segmentos que começam/param no centro de cada seção silenciosa.", | ||
| "Segment tag value": "Valor da tag do segmento", | ||
| "Segments to chapters mode is active, this means that the file will not be cut. Instead chapters will be created from the segments.": "O modo de segmentos para capítulos está ativo, o que significa que o arquivo não será cortado. Em vez disso, capítulos serão criados a partir dos segmentos.", | ||
| "Shift all end times": "Mudar todos os tempos finais", | ||
| "Shift all start times": "Mudar todos os tempos iniciais", | ||
| "Show GPS map": "Mostrar mapa do GPS", | ||
| "Show informational in-app notifications": "Mostrar notificações informativas no aplicativo", | ||
| "Shrink segments -5 sec": "Diminuir segmentos em -5 seg", | ||
| "Smart cut auto detect bitrate": "Taxa de bits de detecção do corte automático inteligente", | ||
| "Smart cut is experimental and will not work on all files.": "O corte inteligente é experimental e não funcionará em todos os arquivos.", | ||
| "Source file's time minus segment end cut time": "Tempo do arquivo de origem menos o tempo de corte do segmento final", | ||
| "Source file's time plus segment start cut time": "Tempo do arquivo de origem mais tempo de corte do segmento inicial", | ||
| "There is a known issue in FFmpeg with cutting FLAC files. The file will be re-encoded, which is still lossless, but the export may be slower.": "Há um problema conhecido no FFmpeg com o corte de arquivos FLAC. O arquivo será recodificado, sem perdas, mas a exportação pode ser mais lenta.", | ||
| "This file contains an audio track that FFmpeg is unable to mux into the MP4 format, so MOV has been auto-selected as the default output format.": "Este arquivo contém uma faixa de áudio que o FFmpeg não consegue mixar no formato MP4, então o MOV foi selecionado automaticamente como o formato de saída padrão.", | ||
| "This gives you an overview of the export and allows you to customise more parameters before exporting, like changing the output file name.": "Isso lhe dá uma visão geral da exportação e permite que você personalize mais parâmetros antes de exportar, como alterar o nome do arquivo de saída.", | ||
| "This option allows you to shift all segment start times forward by one or more frames before cutting. This can be useful if the output video starts from the wrong (preceding) keyframe.": "Esta opção permite adiantar todos os horários de início dos segmentos em um ou mais quadros antes do corte. Isso pode ser útil se o vídeo de saída começar no quadro-chave errado (anterior).", | ||
| "This option lets you losslessly change the speed at which media players will play back the exported file. For example if you double the FPS, the playback speed will double (and duration will halve), however all the frames will be intact and played back (but faster). Be careful not to set it too high, as the player might not be able to keep up (playback CPU usage will increase proportionally to the speed!)": "Esta opção permite alterar sem perdas a velocidade com que os reprodutores de mídia reproduzirão o arquivo exportado. Por exemplo, se você dobrar o FPS, a velocidade de reprodução dobrará (e a duração será reduzida pela metade), porém todos os quadros permanecerão intactos e reproduzidos (mas mais rápido). Tenha cuidado para não definir um valor muito alto, pois o reprodutor pode não conseguir acompanhar (o uso da CPU na reprodução aumentará proporcionalmente à velocidade!)", | ||
| "Timeline keyboard seek interval": "Intervalo de busca do teclado da linha do tempo", | ||
| "Timeline keyboard seek interval (longer)": "Intervalo de busca do teclado na linha do tempo (longo)", | ||
| "Timeline keyboard seek interval (longest)": "Intervalo de busca do teclado na linha do tempo (mais longo)", | ||
| "Toggle {{type}} tracks": "Alternar faixas {{type}}", | ||
| "Toggle all tracks": "Alterar todas as faixas", | ||
| "Toggle dark mode": "Alternar modo escuro", | ||
| "Toggle tracks by expression": "Alternar faixas por expressão", | ||
| "Toggle tracks using current filter": "Alternar faixas usando filtro atual", | ||
| "Treat source file modification date/time as:": "Trate a data/hora de modificação do arquivo de origem como:", | ||
| "Use + and - for relative seek": "Use + e - para busca relativa", | ||
| "When merging, it's generally recommended to set this to \"make_non_negative\"": "Ao mesclar, geralmente é recomendado definir isso como \"make_non_negative\"", | ||
| "Whether to preserve chapters from source file.": "Se os capítulos do arquivo de origem devem ser preservados.", | ||
| "Whether to preserve metadata from source file. Default: Global (file metadata), per-track and per-chapter metadata will be copied. Non-global: Only per-track and per-chapter metadata will be copied. None: No metadata will be copied": "Se os metadados do arquivo de origem devem ser preservados. Padrão: Global (metadados do arquivo), metadados por faixa e por capítulo serão copiados. Não global: Somente metadados por faixa e por capítulo serão copiados. Nenhum: Nenhum metadado será copiado.", | ||
| "You are not allowed to write the output file. This probably means that the file already exists with the wrong permissions, or you don't have write permissions to the output folder.": "Você não tem permissão para salvar o arquivo de saída. Isso provavelmente significa que o arquivo já existe com as permissões erradas ou que você não tem permissão de gravação na pasta de saída.", | ||
| "You can customize the file name of the merged file using special variables.": "Você pode personalizar o nome do arquivo mesclado usando variáveis especiais.", | ||
| "You have enabled the \"invert segments\" mode <1></1> which will cut away selected segments instead of keeping them. But there is no space between any segments, or at least two segments are overlapping. This would not produce any output. Either make room between segments or click the Yinyang <3></3> symbol below to disable this mode. Alternatively you may combine overlapping segments from the menu.": "Você ativou o modo \"inverter segmentos\" <1></1>, que corta os segmentos selecionados em vez de mantê-los. Mas não há espaço entre os segmentos, ou pelo menos dois segmentos estão sobrepostos. Isso não produzirá nenhuma saída. Crie espaço entre os segmentos ou clique no símbolo Yinyang <3></3> abaixo para desativar este modo. Como alternativa, você pode combinar segmentos sobrepostos no menu." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Validate placeholder parity and JSON correctness (automated check).
Large block with many ICU-style placeholders. Let’s verify that each translation preserves exactly the placeholders present in its English key string.
Run this script from repo root:
Expected result:
- “JSON parse OK …”
- “All placeholders match …”
If mismatches appear, please fix the listed entries accordingly.
---
🏁 Script executed:
```shell
#!/bin/bash
set -euo pipefail
files=(
"locales/cs/translation.json"
"locales/tr/translation.json"
"locales/pt_BR/translation.json"
)
# 1) JSON validity
for f in "${files[@]}"; do
jq -e type "$f" >/dev/null
done
echo "JSON parse OK for ${#files[@]} files."
# 2) Placeholder parity check: compare {{placeholders}} in key vs translation
python - <<'PY'
import json, re, sys, pathlib
files = [
"locales/cs/translation.json",
"locales/tr/translation.json",
"locales/pt_BR/translation.json",
]
pat = re.compile(r"\{\{\s*([a-zA-Z0-9_\.]+)\s*\}\}")
def ph(s): return set(pat.findall(s or ""))
errs = []
for fp in files:
data = json.load(open(fp, "r", encoding="utf-8"))
for k, v in data.items():
pk, pv = ph(k), ph(v)
if pk != pv:
errs.append((fp, k, sorted(pk), sorted(pv)))
if errs:
print("MISMATCHES FOUND:")
for fp, k, pk, pv in errs[:50]:
print(f"- {fp}\n key: {k}\n key_placeholders={pk}\n val_placeholders={pv}\n")
sys.exit(1)
print("All placeholders match between keys and translations.")
PY
Length of output: 840
I need to verify the scope of the mismatch found. Let me check if the problematic key is within the reviewed lines or elsewhere in the file.<!-- [scratchpad_update]
[observation_update]
- Web search confirmed jq is the proper tool for JSON parsing in shell
- Line numbers are not meaningful for JSON objects (keys are unordered in JSON spec)
- Need to locate the pt_BR entry with mismatch using Python JSON parser
[analysis_update] - The "Extracting {{count}}" mismatch found is at an unknown position in the pt_BR file
- The provided snippet (lines 877-959) does not contain this key
- Since pt_BR is a flat key-value JSON object (not an array), "line numbers" in the snippet are arbitrary
- Critical issue: the review comment references "lines 877-959" but JSON key order is not guaranteed
- Review comment's scope appears to be the manually provided snippet, NOT the actual file lines 877-959
[scratchpad_end] -->
Now let me locate where the pt_BR mismatch actually is and verify whether it's in the provided snippet:Now let me search for the specific mismatch in the pt_BR file and verify if it's in the provided snippet:
[/code]
Once those results come back, I'll have a complete picture of whether the mismatch is actually in the reviewed range or outside it.
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Check if "Extracting {{count}}" key exists in pt_BR and what its value is
python3 - <<'PY'
import json
with open("locales/pt_BR/translation.json", "r", encoding="utf-8") as f:
data = json.load(f)
# Search for the problematic key
key_to_find = "Extracting {{count}} unprocessable tracks_one"
if key_to_find in data:
print(f"Found key: {key_to_find}")
print(f"Value: {data[key_to_find]}")
else:
print(f"Key not found in pt_BR: {key_to_find}")
# Now check if the provided snippet keys are present
snippet_keys = [
"Subtitles (SRT)",
"You have enabled the \"invert segments\" mode <1></1> which will cut away selected segments instead of keeping them. But there is no space between any segments, or at least two segments are overlapping. This would not produce any output. Either make room between segments or click the Yinyang <3></3> symbol below to disable this mode. Alternatively you may combine overlapping segments from the menu."
]
print("\n--- Snippet Keys Check ---")
for k in snippet_keys:
if k in data:
print(f"✓ Found: {k[:50]}...")
else:
print(f"✗ Not found: {k[:50]}...")
# List all keys with "Extracting" to see what's there
print("\n--- All 'Extracting' keys in pt_BR ---")
extracting_keys = [k for k in data.keys() if "Extracting" in k]
for k in extracting_keys:
print(f" - {k}")
print(f" Value: {data[k][:80]}...")
PYLength of output: 634
The reviewed lines (877-959) pass validation, but a critical placeholder mismatch exists elsewhere in pt_BR.
The provided snippet at lines 877-959 has correct placeholder parity. However, the automated check revealed a critical issue in the same file:
- Key:
Extracting {{count}} unprocessable tracks_one - Current value:
Extraindo uma faixa improcessável(missing{{count}}) - Should be: A translation that includes
{{count}}(like the plural variant does:Extraindo {{count}} faixas improcessáveis)
Fix the singular tracks_one entry to preserve the {{count}} placeholder in its translation.
🤖 Prompt for AI Agents
locales/pt_BR/translation.json around lines 877-959: The singular translation
for key "Extracting {{count}} unprocessable tracks_one" is missing the {{count}}
placeholder; update its value from "Extraindo uma faixa improcessável" to
include the placeholder (e.g. "Extraindo {{count}} faixa improcessável") so it
matches the plural form's placeholder usage.
856dd11 to
cf4b154
Compare
Currently translated at 100.0% (812 of 812 strings) Translation: LosslessCut/LosslessCut Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/zh_Hans/
Currently translated at 100.0% (812 of 812 strings) Translation: LosslessCut/LosslessCut Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/it/
Currently translated at 100.0% (812 of 812 strings) Translation: LosslessCut/LosslessCut Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/tr/
Currently translated at 100.0% (812 of 812 strings) Translation: LosslessCut/LosslessCut Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/hu/
Currently translated at 95.8% (778 of 812 strings) Translation: LosslessCut/LosslessCut Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/pt_BR/
Currently translated at 99.8% (811 of 812 strings) Translation: LosslessCut/LosslessCut Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/cs/
Currently translated at 100.0% (812 of 812 strings) Translation: LosslessCut/LosslessCut Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/ru/
Currently translated at 100.0% (812 of 812 strings) Translation: LosslessCut/LosslessCut Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/de/
Currently translated at 100.0% (812 of 812 strings) Translation: LosslessCut/LosslessCut Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/de/
Currently translated at 100.0% (812 of 812 strings) Translation: LosslessCut/LosslessCut Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/pt_BR/
Currently translated at 100.0% (812 of 812 strings) Translation: LosslessCut/LosslessCut Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/cs/
Currently translated at 100.0% (812 of 812 strings) Translation: LosslessCut/LosslessCut Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/de/
Currently translated at 100.0% (812 of 812 strings) Translation: LosslessCut/LosslessCut Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/de/
Currently translated at 100.0% (827 of 827 strings) Translation: LosslessCut/LosslessCut Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/it/
Currently translated at 100.0% (827 of 827 strings) Translation: LosslessCut/LosslessCut Translate-URL: https://hosted.weblate.org/projects/losslesscut/losslesscut/tr/
cf4b154 to
1b116cc
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (3)
locales/it/translation.json (1)
960-976: Repo-wide key parity sanity check (follow-up to earlier comment)Validate that all locales include the newly introduced keys (not only “Make cursor time zero”, but also: “Apply change”, “Apply filter”, “Auto merge segments into one file after export, but keep exported per-segment files too”, “Error”, “Export each segment to a separate file”, “Go”, “Invalid timecode format”, “Loop selected segments in order”, “Please confirm”, “Reduce motion in user interface”, “Select segments”, “Setting”, “Success!”, “System default”, “The audio track is not supported while previewing. You can convert to a supported format from the menu”).
Run:
#!/usr/bin/env bash set -euo pipefail keys=( "Make cursor time zero" "Apply change" "Apply filter" "Auto merge segments into one file after export, but keep exported per-segment files too" "Error" "Export each segment to a separate file" "Go" "Invalid timecode format" "Loop selected segments in order" "Please confirm" "Reduce motion in user interface" "Select segments" "Setting" "Success!" "System default" "The audio track is not supported while previewing. You can convert to a supported format from the menu" ) miss=0 for f in locales/*/translation.json; do for k in "${keys[@]}"; do if ! jq -e --arg k "$k" 'has($k)' "$f" >/dev/null; then echo "MISSING: $k -> $f" miss=1 fi done # also validate JSON structure jq -e . "$f" >/dev/null done if [ $miss -eq 0 ]; then echo "All locales contain all new keys." else echo "Some locales are missing keys (see MISSING lines above)." exit 1 filocales/pt_BR/translation.json (2)
640-640: Critical: Placeholder mismatch remains unresolved from previous review.This issue was already flagged in an earlier review. The translation is still missing the
{{count}}placeholder that exists in the key.Current:
"Extracting {{count}} unprocessable tracks_one": "Extraindo uma faixa improcessável"The value should include
{{count}}to match the plural variant and function correctly:- "Extracting {{count}} unprocessable tracks_one": "Extraindo uma faixa improcessável", + "Extracting {{count}} unprocessable tracks_one": "Extraindo {{count}} faixa improcessável",
914-914: Grammar: Use formal imperative form.This issue was flagged in a previous review. The translation uses the informal verb form "seleciona" instead of the formal imperative "selecione".
- "Please select a working directory first": "Por favor, seleciona uma pasta de trabalho primeiro", + "Please select a working directory first": "Por favor, selecione uma pasta de trabalho primeiro",
🧹 Nitpick comments (3)
locales/it/translation.json (1)
961-976: Polish recent Italian additions for grammar and clarityTighten phrasing, fix singular/plural, and punctuation.
Apply this diff:
- "Make cursor time zero": "Rendi il tempo del cursore zero", + "Make cursor time zero": "Imposta a zero il tempo del cursore", - "Apply change": "Applica modifiche", + "Apply change": "Applica modifica", - "Auto merge segments into one file after export, but keep exported per-segment files too": "Dopo l'esportazione unisci automaticamente i segmenti in un unico file , ma conserva anche i file esportati per segmento", + "Auto merge segments into one file after export, but keep exported per-segment files too": "Dopo l'esportazione, unisci automaticamente i segmenti in un unico file, ma conserva anche i file esportati per segmento", - "Reduce motion in user interface": "Riduci movimento interfaccia utente", + "Reduce motion in user interface": "Riduci il movimento nell'interfaccia utente", - "Setting": "Impostazioni", + "Setting": "Impostazione", - "Success!": "Completato!", + "Success!": "Operazione riuscita!", - "System default": "Predefinito sistema", + "System default": "Predefinito di sistema"locales/cs/translation.json (1)
1004-1005: Minor style tweak for “Make cursor time zero”More idiomatic Czech:
- "Make cursor time zero": "Nastavit čas v místě kurzoru jako nulový" + "Make cursor time zero": "Nastavit čas v místě kurzoru na nulu"locales/tr/translation.json (1)
985-986: Fix “Setting” noun and refine “System default”Current “Ayarlanıyor” is a verb form. Use the noun.
- "Setting": "Ayarlanıyor", + "Setting": "Ayar", - "System default": "Sistem öntanımlı değeri", + "System default": "Sistem varsayılanı"Optionally, for a clearer toast:
- "Success!": "Başarılı!", + "Success!": "İşlem başarılı!"
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
locales/cs/translation.json(3 hunks)locales/hu/translation.json(1 hunks)locales/it/translation.json(1 hunks)locales/pt_BR/translation.json(2 hunks)locales/ru/translation.json(1 hunks)locales/tr/translation.json(1 hunks)locales/zh_Hans/translation.json(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- locales/ru/translation.json
- locales/zh_Hans/translation.json
- locales/hu/translation.json
🔇 Additional comments (4)
locales/it/translation.json (1)
960-960: JSON formatting LGTMTrailing comma added after "Video tracks" is correct and keeps the JSON valid with following entries.
locales/cs/translation.json (2)
702-702: Phrasing improvement LGTMUpdated to “Doporučuje se nastavit toto na: {{values}}” is clearer.
924-924: Metadata option description LGTMDash-separated phrasing reads better; no functional change.
locales/tr/translation.json (1)
971-984: New Turkish entries look consistentKeys added after “Video tracks” with correct JSON punctuation; translations are accurate.
Translations update from Hosted Weblate for LosslessCut/LosslessCut.
Current translation status:
Summary by CodeRabbit
New Features
Bug Fixes / Tweaks