fix: localize file type labels

This commit is contained in:
mirivlad 2026-07-15 03:13:48 +08:00
parent 484d599a9f
commit c9c26faf56
4 changed files with 67 additions and 7 deletions

View File

@ -224,7 +224,7 @@
return EXT_MAP[ext] || 'generic';
}
function fileIconLabel(category) {
function fileIconLabel(category, translate) {
var labels = {
folder: 'Folder',
markdown: 'Markdown file',
@ -244,7 +244,8 @@
json: 'JSON file',
generic: 'File'
};
return labels[category] || labels.generic;
var label = labels[category] || labels.generic;
return typeof translate === 'function' ? translate('ui.icon.' + (labels[category] ? category : 'generic'), null, label) : label;
}
function fileIcon(entry) {
@ -267,8 +268,8 @@
return date.toLocaleString(undefined, { year: 'numeric', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' });
}
function typeLabel(entry) {
if (entry.type === 'folder') return 'folder';
function typeLabel(entry, folderLabel) {
if (entry.type === 'folder') return folderLabel || 'Folder';
return (entry.extension || extension(entry.name) || 'file').toLowerCase();
}
@ -383,6 +384,10 @@
return fallback || key;
}
function displayType(entry) {
return typeLabel(entry, tr('ui.folderType', null, 'Folder'));
}
function reportError(key, fallback, err) {
if (typeof console !== 'undefined' && typeof console.warn === 'function') {
console.warn('[verstak.files] ' + key, err);
@ -523,7 +528,7 @@
if (a.type !== 'folder' && b.type === 'folder') return 1;
}
if (sortMode === 'type') {
var typeCmp = typeLabel(a).localeCompare(typeLabel(b));
var typeCmp = displayType(a).localeCompare(displayType(b));
if (typeCmp) return typeCmp;
}
if (sortMode === 'modified-desc') {
@ -645,7 +650,7 @@
shown.forEach(function (entry) {
var iconCategory = fileIconCategory(entry);
var iconLabel = fileIconLabel(iconCategory);
var iconLabel = fileIconLabel(iconCategory, tr);
var row = el('div', {
className: 'files-item' + (selectedPaths[entry.relativePath] ? ' selected' : ''),
'data-file-name': entry.name,
@ -678,7 +683,7 @@
el('span', { className: 'files-item-icon', 'data-file-icon': iconCategory, title: iconLabel, 'aria-label': iconLabel, innerHTML: fileIcon(entry) }),
el('span', { className: 'files-item-name', textContent: entry.name, title: entry.name })
]),
el('span', { className: 'files-item-meta' }, [typeLabel(entry)]),
el('span', { className: 'files-item-meta' }, [displayType(entry)]),
el('span', { className: 'files-item-meta hide-narrow' }, [entry.type === 'folder' ? '' : formatSize(entry.size)]),
el('span', { className: 'files-item-meta hide-narrow' }, [formatDate(entry.modifiedAt)]),
el('div', { className: 'files-row-actions' }, [

View File

@ -26,6 +26,24 @@
"ui.column.modified": "Modified",
"ui.column.size": "Size",
"ui.column.actions": "Actions",
"ui.folderType": "Folder",
"ui.icon.folder": "Folder",
"ui.icon.markdown": "Markdown file",
"ui.icon.image": "Image file",
"ui.icon.video": "Video file",
"ui.icon.audio": "Audio file",
"ui.icon.archive": "Archive file",
"ui.icon.pdf": "PDF file",
"ui.icon.text": "Text file",
"ui.icon.document": "Document file",
"ui.icon.spreadsheet": "Spreadsheet file",
"ui.icon.presentation": "Presentation file",
"ui.icon.code": "Code file",
"ui.icon.database": "Database file",
"ui.icon.font": "Font file",
"ui.icon.config": "Config file",
"ui.icon.json": "JSON file",
"ui.icon.generic": "File",
"ui.create": "Create",
"ui.cancel": "Cancel",
"ui.createFolderTitle": "Create folder",

View File

@ -26,6 +26,24 @@
"ui.column.modified": "Изменён",
"ui.column.size": "Размер",
"ui.column.actions": "Действия",
"ui.folderType": "Папка",
"ui.icon.folder": "Папка",
"ui.icon.markdown": "Файл Markdown",
"ui.icon.image": "Изображение",
"ui.icon.video": "Видео",
"ui.icon.audio": "Аудиофайл",
"ui.icon.archive": "Архив",
"ui.icon.pdf": "PDF-файл",
"ui.icon.text": "Текстовый файл",
"ui.icon.document": "Документ",
"ui.icon.spreadsheet": "Таблица",
"ui.icon.presentation": "Презентация",
"ui.icon.code": "Исходный код",
"ui.icon.database": "База данных",
"ui.icon.font": "Шрифт",
"ui.icon.config": "Файл конфигурации",
"ui.icon.json": "JSON-файл",
"ui.icon.generic": "Файл",
"ui.create": "Создать",
"ui.cancel": "Отмена",
"ui.createFolderTitle": "Создать папку",

View File

@ -233,6 +233,15 @@ function makeApi(options = {}) {
size: 12,
modifiedAt: '2026-06-27T00:00:00Z',
}];
if (options.includeFolder) {
entries.push({
name: 'Archive',
relativePath: 'Docs/Archive',
type: 'folder',
size: 0,
modifiedAt: '2026-06-27T00:00:00Z',
});
}
if (restored) {
entries.push({
name: 'deleted.md',
@ -456,6 +465,7 @@ async function flush() {
const russianDocument = makeDocument();
const { component: russianComponent } = loadFilesComponent(russianDocument);
const russianApi = makeApi({
includeFolder: true,
translations: {
'ui.open': 'Открыть',
'ui.openExternal': 'Открыть во внешнем приложении',
@ -465,13 +475,22 @@ async function flush() {
'ui.cut': 'Вырезать',
'ui.copy': 'Копировать',
'ui.trash': 'Переместить в корзину',
'ui.folderType': 'Папка',
'ui.icon.markdown': 'Файл Markdown',
},
});
const russianContainer = new FakeNode('div');
russianComponent.mount(russianContainer, {}, russianApi);
await flush();
if (!russianContainer.textContent.includes('Папка') || russianContainer.textContent.includes('folder')) {
throw new Error(`folder type was not localized: ${russianContainer.textContent}`);
}
const russianList = walk(russianContainer, (node) => node.getAttribute && node.getAttribute('data-files-list') !== undefined);
const russianRow = walk(russianContainer, (node) => node.getAttribute && node.getAttribute('data-file-path') === 'Docs/readme.md');
const russianIcon = walk(russianRow, (node) => node.getAttribute && node.getAttribute('data-file-icon') === 'markdown');
if (!russianIcon || russianIcon.getAttribute('title') !== 'Файл Markdown' || russianIcon.getAttribute('aria-label') !== 'Файл Markdown') {
throw new Error(`file icon label was not localized: ${russianIcon && russianIcon.getAttribute('title')}`);
}
russianList.dispatchEvent('contextmenu', { target: russianRow, clientX: 20, clientY: 20 });
const russianMenuText = russianDocument.body.textContent;
['Открыть во внешнем приложении', 'Показать в папке', 'Переименовать', 'Создать копию', 'Вырезать', 'Копировать', 'Переместить в корзину'].forEach((label) => {