feat: localize official plugins in Russian
This commit is contained in:
@@ -273,18 +273,22 @@
|
||||
|
||||
var scope = scopeFromProps(props || {});
|
||||
var entries = [];
|
||||
var statusText = 'Loading journal...';
|
||||
function tr(key, params, fallback) {
|
||||
if (api && api.i18n && typeof api.i18n.t === 'function') return api.i18n.t(key, params, fallback);
|
||||
return fallback || key;
|
||||
}
|
||||
var statusText = tr('ui.loading', null, 'Loading journal...');
|
||||
var statusClass = '';
|
||||
var modalHost = el('div', { className: 'journal-modal-host', hidden: 'hidden' });
|
||||
|
||||
var toolbar = el('div', { className: 'journal-toolbar' });
|
||||
var titleEl = el('span', { className: 'journal-title', textContent: scope.mode === 'global' ? 'Journal' : 'Journal · ' + scope.label });
|
||||
var titleEl = el('span', { className: 'journal-title', textContent: scope.mode === 'global' ? tr('ui.title', null, 'Journal') : tr('ui.workspaceTitle', { workspace: scope.label }, 'Journal · ' + scope.label) });
|
||||
var countEl = el('span', { className: 'journal-count' });
|
||||
var statusEl = el('span', { className: 'journal-status' });
|
||||
var addBtn = el('button', {
|
||||
className: 'journal-btn primary',
|
||||
'data-journal-action': 'add',
|
||||
innerHTML: iconSvg('add') + '<span>Add</span>',
|
||||
innerHTML: iconSvg('add') + '<span>' + tr('ui.add', null, 'Add') + '</span>',
|
||||
onClick: function () { showEntryModal(); }
|
||||
});
|
||||
toolbar.appendChild(titleEl);
|
||||
@@ -302,7 +306,7 @@
|
||||
if (scope.mode !== 'workspace') return Promise.resolve();
|
||||
if (!api || !api.settings || typeof api.settings.write !== 'function') return Promise.resolve();
|
||||
return api.settings.write(scope.key, storageEntries(entries)).catch(function (err) {
|
||||
statusText = 'Could not save journal: ' + (err && err.message ? err.message : String(err));
|
||||
statusText = tr('ui.saveError', { error: err && err.message ? err.message : String(err) }, 'Could not save journal: ' + (err && err.message ? err.message : String(err)));
|
||||
statusClass = 'error';
|
||||
});
|
||||
}
|
||||
@@ -316,19 +320,19 @@
|
||||
all = all.concat(normalizeEntries((settings || {})[key], key));
|
||||
});
|
||||
entries = sortEntries(all);
|
||||
statusText = 'Aggregating worklogs';
|
||||
statusText = tr('ui.aggregating', null, 'Aggregating worklogs');
|
||||
statusClass = '';
|
||||
}).catch(function (err) {
|
||||
statusText = 'Could not load journal: ' + (err && err.message ? err.message : String(err));
|
||||
statusText = tr('ui.loadError', { error: err && err.message ? err.message : String(err) }, 'Could not load journal: ' + (err && err.message ? err.message : String(err)));
|
||||
statusClass = 'error';
|
||||
});
|
||||
}
|
||||
return api.settings.read(scope.key).then(function (stored) {
|
||||
entries = sortEntries(normalizeEntries(stored, scope.key));
|
||||
statusText = 'Ready';
|
||||
statusText = tr('ui.ready', null, 'Ready');
|
||||
statusClass = '';
|
||||
}).catch(function (err) {
|
||||
statusText = 'Could not load journal: ' + (err && err.message ? err.message : String(err));
|
||||
statusText = tr('ui.loadError', { error: err && err.message ? err.message : String(err) }, 'Could not load journal: ' + (err && err.message ? err.message : String(err)));
|
||||
statusClass = 'error';
|
||||
});
|
||||
}
|
||||
@@ -344,8 +348,8 @@
|
||||
var reviewingCandidate = !editing && !!candidate;
|
||||
var reviewingTodo = !editing && !!completedTodo;
|
||||
var dateInput = el('input', { className: 'journal-input', type: 'date', value: editing ? existingEntry.date : (reviewingCandidate ? candidateDate(candidate.startedAt) : (reviewingTodo ? candidateDate(completedTodo.completedAt) : today())), 'data-journal-input': 'date' });
|
||||
var titleInput = el('input', { className: 'journal-input', type: 'text', placeholder: 'Work item', value: editing ? existingEntry.title : (reviewingTodo ? completedTodo.title : ''), 'data-journal-input': 'title' });
|
||||
var summaryInput = el('textarea', { className: 'journal-input textarea', placeholder: 'Body', 'data-journal-input': 'summary' });
|
||||
var titleInput = el('input', { className: 'journal-input', type: 'text', placeholder: tr('ui.workItem', null, 'Work item'), value: editing ? existingEntry.title : (reviewingTodo ? completedTodo.title : ''), 'data-journal-input': 'title' });
|
||||
var summaryInput = el('textarea', { className: 'journal-input textarea', placeholder: tr('ui.body', null, 'Body'), 'data-journal-input': 'summary' });
|
||||
summaryInput.value = editing ? existingEntry.summary : (reviewingTodo ? completedTodo.description : '');
|
||||
var minutesInput = el('input', { className: 'journal-input', type: 'number', min: '0', step: '1', value: editing ? existingEntry.minutes : (reviewingCandidate ? candidate.estimatedMinutes : (reviewingTodo ? '0' : '30')), 'data-journal-input': 'minutes' });
|
||||
var billableInput = el('input', { type: 'checkbox', 'data-journal-input': 'billable' });
|
||||
@@ -397,20 +401,20 @@
|
||||
if (event.target === event.currentTarget) closeEntryModal();
|
||||
} }, [
|
||||
el('div', { className: 'journal-modal' }, [
|
||||
el('div', { className: 'journal-modal-title', textContent: editing ? 'Edit journal entry' : (reviewingCandidate ? 'Review possible journal entry' : (reviewingTodo ? 'Create journal entry from completed todo' : 'Add journal entry')) }),
|
||||
el('div', { className: 'journal-modal-title', textContent: editing ? tr('ui.editEntry', null, 'Edit journal entry') : (reviewingCandidate ? tr('ui.reviewCandidate', null, 'Review possible journal entry') : (reviewingTodo ? tr('ui.fromTodo', null, 'Create journal entry from completed todo') : tr('ui.addEntry', null, 'Add journal entry'))) }),
|
||||
candidateContext,
|
||||
todoContext,
|
||||
el('div', { className: 'journal-modal-grid' }, [
|
||||
el('label', { className: 'journal-field' }, ['Date', dateInput]),
|
||||
el('label', { className: 'journal-field' }, ['Minutes', minutesInput]),
|
||||
el('label', { className: 'journal-field wide' }, ['Title', titleInput]),
|
||||
el('label', { className: 'journal-field wide' }, ['Body', summaryInput]),
|
||||
el('label', { className: 'journal-billable' }, [billableInput, 'Billable'])
|
||||
el('label', { className: 'journal-field' }, [tr('ui.date', null, 'Date'), dateInput]),
|
||||
el('label', { className: 'journal-field' }, [tr('ui.minutes', null, 'Minutes'), minutesInput]),
|
||||
el('label', { className: 'journal-field wide' }, [tr('ui.fieldTitle', null, 'Title'), titleInput]),
|
||||
el('label', { className: 'journal-field wide' }, [tr('ui.body', null, 'Body'), summaryInput]),
|
||||
el('label', { className: 'journal-billable' }, [billableInput, tr('ui.billable', null, 'Billable')])
|
||||
]),
|
||||
candidateActivities,
|
||||
el('div', { className: 'journal-modal-actions' }, [
|
||||
el('button', { className: 'journal-btn ghost', type: 'button', textContent: 'Cancel', onClick: closeEntryModal }),
|
||||
el('button', { className: 'journal-btn primary', type: 'button', 'data-journal-action': 'save-entry', textContent: editing ? 'Save changes' : 'Add entry', onClick: saveEntry })
|
||||
el('button', { className: 'journal-btn ghost', type: 'button', textContent: tr('ui.cancel', null, 'Cancel'), onClick: closeEntryModal }),
|
||||
el('button', { className: 'journal-btn primary', type: 'button', 'data-journal-action': 'save-entry', textContent: editing ? tr('ui.saveChanges', null, 'Save changes') : tr('ui.addEntryShort', null, 'Add entry'), onClick: saveEntry })
|
||||
])
|
||||
])
|
||||
]));
|
||||
@@ -421,7 +425,7 @@
|
||||
if (scope.mode !== 'workspace') return;
|
||||
var title = text(formValue && formValue.title).trim();
|
||||
if (!title) {
|
||||
statusText = 'Title is required';
|
||||
statusText = tr('ui.titleRequired', null, 'Title is required');
|
||||
statusClass = 'error';
|
||||
render();
|
||||
return;
|
||||
@@ -469,7 +473,7 @@
|
||||
function deleteEntry(entry) {
|
||||
if (scope.mode !== 'workspace' || !entry) return;
|
||||
entries = entries.filter(function (item) { return item.entryId !== entry.entryId; });
|
||||
statusText = 'Entry deleted';
|
||||
statusText = tr('ui.deleted', null, 'Entry deleted');
|
||||
statusClass = '';
|
||||
persist().then(render);
|
||||
}
|
||||
@@ -477,7 +481,7 @@
|
||||
function renderList() {
|
||||
listEl.innerHTML = '';
|
||||
if (!entries.length) {
|
||||
listEl.appendChild(el('div', { className: 'journal-empty', textContent: scope.mode === 'global' ? 'No worklog entries yet.' : 'No worklog entries yet.' }));
|
||||
listEl.appendChild(el('div', { className: 'journal-empty', textContent: tr('ui.empty', null, 'No worklog entries yet.') }));
|
||||
return;
|
||||
}
|
||||
entries.forEach(function (entry) {
|
||||
@@ -493,8 +497,8 @@
|
||||
]),
|
||||
el('div', { className: 'journal-minutes', textContent: entry.minutes + ' min' }),
|
||||
scope.mode === 'workspace' ? el('div', { className: 'journal-row-actions' }, [
|
||||
el('button', { className: 'journal-icon-btn', type: 'button', title: 'Edit', 'aria-label': 'Edit', 'data-journal-action': 'edit', innerHTML: iconSvg('edit'), onClick: function () { showEntryModal(entry); } }),
|
||||
el('button', { className: 'journal-icon-btn danger', type: 'button', title: 'Delete', 'aria-label': 'Delete', 'data-journal-action': 'delete', innerHTML: iconSvg('trash'), onClick: function () { deleteEntry(entry); } })
|
||||
el('button', { className: 'journal-icon-btn', type: 'button', title: tr('ui.edit', null, 'Edit'), 'aria-label': tr('ui.edit', null, 'Edit'), 'data-journal-action': 'edit', innerHTML: iconSvg('edit'), onClick: function () { showEntryModal(entry); } }),
|
||||
el('button', { className: 'journal-icon-btn danger', type: 'button', title: tr('ui.delete', null, 'Delete'), 'aria-label': tr('ui.delete', null, 'Delete'), 'data-journal-action': 'delete', innerHTML: iconSvg('trash'), onClick: function () { deleteEntry(entry); } })
|
||||
]) : null
|
||||
]));
|
||||
});
|
||||
@@ -516,6 +520,13 @@
|
||||
if (candidate) showEntryModal(null, candidate);
|
||||
else if (completedTodo) showEntryModal(null, null, completedTodo);
|
||||
});
|
||||
if (api && api.i18n && typeof api.i18n.onDidChangeLocale === 'function') {
|
||||
api.i18n.onDidChangeLocale(function () {
|
||||
titleEl.textContent = scope.mode === 'global' ? tr('ui.title', null, 'Journal') : tr('ui.workspaceTitle', { workspace: scope.label }, 'Journal · ' + scope.label);
|
||||
addBtn.innerHTML = iconSvg('add') + '<span>' + tr('ui.add', null, 'Add') + '</span>';
|
||||
render();
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
JournalView.unmount = function (containerEl) {
|
||||
|
||||
Reference in New Issue
Block a user