Skip to content

Commit

Permalink
add localisationIndex feature flag & add dynamic localisation of prev…
Browse files Browse the repository at this point in the history
…iew content & fix buggy readDirFilesRecursivelyImpl in vsccommon.ts (#95)
  • Loading branch information
IShiraiKurokoI authored Sep 3, 2024
1 parent a121462 commit 480bae0
Show file tree
Hide file tree
Showing 15 changed files with 450 additions and 22 deletions.
7 changes: 7 additions & 0 deletions i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ const internalTable = /* SOT Do not remove this comment */{
"hours": "hour(s)",
"infile": "In file {0}:\n",
"loading": "Loading...",
"localisationIndex.builddone": "Localisation index building done.",
"localisationIndex.building": "Building localisation index...",
"localisationIndex.mod": "[Mod]",
"localisationIndex.parseFailure": "parsing failed! Please check if the file has issues!",
"localisationIndex.vanilla": "[Vanilla]",
"localisationIndex.workspace.builddone": "Workspace localisation index building done.",
"localisationIndex.workspace.building": "Building workspace localisation index...",
"miopreview.conditions": "Conditions: ",
"miopreview.mio": "Military Industrial Organization: ",
"miopreview.nomio": "No military industrial organization defined.",
Expand Down
7 changes: 7 additions & 0 deletions i18n/template.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ const table: Partial<typeof __table> = {
"hours": "hour(s)",
"infile": "In file {0}:\n",
"loading": "Loading...",
"localisationIndex.builddone": "Localisation index building done.",
"localisationIndex.building": "Building localisation index...",
"localisationIndex.mod": "[Mod]",
"localisationIndex.parseFailure": "parsing failed! Please check if the file has issues!",
"localisationIndex.vanilla": "[Vanilla]",
"localisationIndex.workspace.builddone": "Workspace localisation index building done.",
"localisationIndex.workspace.building": "Building workspace localisation index...",
"miopreview.conditions": "Conditions: ",
"miopreview.mio": "Military Industrial Organization: ",
"miopreview.nomio": "No military industrial organization defined.",
Expand Down
7 changes: 7 additions & 0 deletions i18n/zh-cn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ const table: Partial<typeof __table> = {
"hours": "小时",
"infile": "在文件 {0} 中:\n",
"loading": "加载中……",
"localisationIndex.builddone": "本地化索引构建完成。",
"localisationIndex.building": "正在构建本地化索引...",
"localisationIndex.mod": "[模组]",
"localisationIndex.parseFailure": "解析失败!请检查文件是否存在问题!",
"localisationIndex.vanilla": "[原版]",
"localisationIndex.workspace.builddone": "工作区本地化索引构建完成。",
"localisationIndex.workspace.building": "正在构建工作区本地化索引...",
"miopreview.conditions": "条件:",
"miopreview.mio": "军工机构: ",
"miopreview.nomio": "没有军工机构。",
Expand Down
6 changes: 6 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,18 @@ import { registerScanReferencesCommand } from './util/dependency';
import { registerHoiFs } from './util/hoifs';
import { loadI18n } from './util/i18n';
import { registerGfxIndex } from './util/gfxindex';
import { Logger } from "./util/logger";
import { registerLocalisationIndex } from "./util/localisationIndex";

export function activate(context: vscode.ExtensionContext) {
let locale = (context as any).extension?.packageJSON.locale;
if (locale === "%hoi4modutilities.locale%") {
locale = 'en';
}

Logger.initialize();
Logger.show();

loadI18n(locale);

// Must register this first because other component may use it.
Expand All @@ -33,6 +38,7 @@ export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(vscode.window.registerCustomEditorProvider(ViewType.DDS, new DDSViewProvider()));
context.subscriptions.push(vscode.window.registerCustomEditorProvider(ViewType.TGA, new TGAViewProvider()));
context.subscriptions.push(registerGfxIndex());
context.subscriptions.push(registerLocalisationIndex());

if (process.env.NODE_ENV !== 'production') {
vscode.commands.registerCommand('hoi4modutilities.test', () => {
Expand Down
35 changes: 28 additions & 7 deletions src/previewdef/event/contentbuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import { GridBoxType } from '../../hoiformat/gui';
import { renderGridBox, GridBoxItem, GridBoxConnection } from '../../util/hoi4gui/gridbox';
import { Token } from '../../hoiformat/hoiparser';
import { getSpriteByGfxName } from '../../util/image/imagecache';
import { getLocalisedTextQuick } from "../../util/localisationIndex";
import { localisationIndex } from "../../util/featureflags";

export async function renderEventFile(loader: EventsLoader, uri: vscode.Uri, webview: vscode.Webview): Promise<string> {
const setPreviewFileUriScript = { content: `window.previewedFileUri = "${uri.toString()}";` };
Expand Down Expand Up @@ -287,7 +289,7 @@ async function eventNodeToGridBoxItems(
const isOption = typeof node === 'object' && !('event' in node);
const id = (typeof node === 'object' ? ('event' in node ? node.event.id : node.optionName) : node) + ':' + (idContainer.id++);
if (isOption) {
idToContentMap[id] = makeOptionNode(node as OptionNode, eventsLoaderResult, styleTable);
idToContentMap[id] = await makeOptionNode(node as OptionNode, eventsLoaderResult, styleTable);
} else {
idToContentMap[id] = await makeEventNode(scopeContext.currentScopeName,
typeof node === 'object' ? node as EventNode : node, edge, eventsLoaderResult, styleTable);
Expand Down Expand Up @@ -379,7 +381,7 @@ async function makeEventNode(scope: string, eventNode: EventNode | string, edge:
`${edge.randomDays > 0 ? `${edge.days}-${edge.days + edge.randomDays}` : edge.days} ${localize('days', 'day(s)')}` :
`${edge.randomHours > 0 ? `${edge.hours}-${edge.hours + edge.randomHours}` : edge.hours} ${localize('hours', 'hour(s)')}`) + '\n' :
'') +
`${localize('eventtree.scope', 'Scope: ')}${scope}\n${localize('eventtree.title', 'Title: ')}${localizationDict[event.title] ?? event.title}`;
`${localize('eventtree.scope', 'Scope: ')}${scope}\n${localize('eventtree.title', 'Title: ')}${localisationIndex ? await getLocalisedTextQuick(event.title) : event.title}`;

const flags = [event.hidden, event.fire_only_once, event.major, eventNode.loop];
const content = `<p class="
Expand All @@ -401,7 +403,7 @@ async function makeEventNode(scope: string, eventNode: EventNode | string, edge:
: ''}
</p>
<p class="${styleTable.style('paragraph', () => 'margin: 5px 0; text-overflow: ellipsis; overflow: hidden;')}">
${localizationDict[event.title] ?? event.title}
${localisationIndex? await getLocalisedTextQuick(event.title) : event.title}
</p>`;

const extraAttributes = [];
Expand Down Expand Up @@ -443,6 +445,18 @@ async function makeEventNode(scope: string, eventNode: EventNode | string, edge:
} else {
const eventId = eventNode;
const title = `${localize('eventtree.eventid', 'Event ID: ')}${eventId}\n${localize('eventtree.scope', 'Scope: ')}${scope}`;
let contentText = '';
if (localisationIndex) {
let localizedTitle = await getLocalisedTextQuick(eventId);
if (localizedTitle !== eventId && localizedTitle != null) {
contentText += `<br/>${localizedTitle}`;
} else {
localizedTitle = await getLocalisedTextQuick(`${eventId}.t`);
if (localizedTitle !== `${eventId}.t` && localizedTitle != null) {
contentText += `<br/>${localizedTitle}`;
}
}
}
const content = `<p class="
${styleTable.style('paragraph', () => 'margin: 5px 0; text-overflow: ellipsis; overflow: hidden;')}
${styleTable.style('white-space-nowrap', () => 'white-space: nowrap;')}
Expand All @@ -451,6 +465,7 @@ async function makeEventNode(scope: string, eventNode: EventNode | string, edge:
${eventId}
<br/>
${makeIcon('symbol-namespace', styleTable)} ${scope}
${contentText}
</p>`;

return makeNode(content, title, styleTable, styleTable.style('event-item', () => 'background: rgba(255, 80, 80, 0.5);'));
Expand All @@ -461,9 +476,15 @@ function makeIcon(type: string, styleTable: StyleTable): string {
return `<i class="codicon codicon-${type} ${styleTable.style('bottom', () => 'vertical-align: bottom;')}"></i>`;
}

function makeOptionNode(option: OptionNode, eventsLoaderResult: EventsLoaderResult, styleTable: StyleTable): string {
const content = `${eventsLoaderResult.localizationDict[option.optionName] ?? option.optionName}`;

async function makeOptionNode(option: OptionNode, eventsLoaderResult: EventsLoaderResult, styleTable: StyleTable): Promise<string> {
let content = option.optionName;
let title = option.optionName;
if (localisationIndex){
const optionName = await getLocalisedTextQuick(option.optionName);
content = `${option.optionName} <br/> ${optionName}`;
title = `${option.optionName} \n ${optionName}`;
}

const extraAttributes = option.token ? `
start="${option.token.start}"
end="${option.token.end}"
Expand All @@ -472,7 +493,7 @@ function makeOptionNode(option: OptionNode, eventsLoaderResult: EventsLoaderResu

return makeNode(
content,
content,
title,
styleTable,
styleTable.style('event-option', () => 'background: rgba(80, 80, 255, 0.5); cursor: pointer;')
+ (option.token ? ' navigator' : ''),
Expand Down
19 changes: 18 additions & 1 deletion src/previewdef/focustree/contentbuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { debug } from '../../util/debug';
import { StyleTable, normalizeForStyle } from '../../util/styletable';
import { useConditionInFocus } from '../../util/featureflags';
import { flatMap } from 'lodash';
import { getLocalisedTextQuick } from "../../util/localisationIndex";
import { localisationIndex } from "../../util/featureflags";

const defaultFocusIcon = 'gfx/interface/goals/goal_unknown.dds';

Expand Down Expand Up @@ -208,6 +210,21 @@ async function renderFocus(focus: Focus, styleTable: StyleTable, gfxFiles: strin

styleTable.style('focus-icon-' + normalizeForStyle('-empty'), () => 'background: grey;');

let textContent = focus.id;
if (localisationIndex){
let localizedText = await getLocalisedTextQuick(focus.id);
if (localizedText === focus.id || !localizedText){
if (focus.text){
localizedText = await getLocalisedTextQuick(focus.text);
if (localizedText !== focus.text && localizedText != null){
textContent += `<br/>${localizedText}`;
}
}
}else {
textContent += `<br/>${localizedText}`;
}
}

return `<div
class="
navigator
Expand Down Expand Up @@ -236,7 +253,7 @@ async function renderFocus(focus: Focus, styleTable: StyleTable, gfxFiles: strin
text-align: center;
display: inline-block;
`)}">
${focus.id}
${textContent}
</span>
</div>`;
}
Expand Down
8 changes: 7 additions & 1 deletion src/previewdef/focustree/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export interface Focus {
offset: Offset[];
token: Token | undefined;
file: string;
text?: string;
}

export interface FocusWarning extends Warning<string> {
Expand Down Expand Up @@ -68,6 +69,7 @@ interface FocusDef {
allow_branch: Raw[]; /* FIXME not symbol node */
offset: OffsetDef[];
_token: Token;
text?: string;
}

interface FocusIconDef {
Expand Down Expand Up @@ -134,7 +136,8 @@ const focusSchema: SchemaDef<FocusDef> = {
},
},
_type: 'array',
}
},
text: "string",
};

const focusTreeSchema: SchemaDef<FocusTreeDef> = {
Expand Down Expand Up @@ -305,6 +308,8 @@ function getFocus(hoiFocus: HOIPartial<FocusDef>, conditionExprs: ConditionItem[
trigger: o.trigger ? extractConditionValues(o.trigger.filter((v): v is Raw => v !== undefined).map(v => v._raw.value), countryScope, conditionExprs).condition : false,
}));

const text = hoiFocus.text;

return {
id,
icon,
Expand All @@ -319,6 +324,7 @@ function getFocus(hoiFocus: HOIPartial<FocusDef>, conditionExprs: ConditionItem[
offset,
token: hoiFocus._token,
file: filePath,
text,
};
}

Expand Down
26 changes: 22 additions & 4 deletions src/previewdef/mio/contentbuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { LoaderSession } from '../../util/loader/loader';
import { debug } from '../../util/debug';
import { StyleTable, normalizeForStyle } from '../../util/styletable';
import { Mio, MioTrait, TraitEffect } from './schema';
import { getLocalisedTextQuick } from "../../util/localisationIndex";
import { localisationIndex } from "../../util/featureflags";

const defaultTraitIcon = 'gfx/interface/goals/goal_unknown.dds';
const traitEffectIconMap: Record<TraitEffect, string> = {
Expand Down Expand Up @@ -105,7 +107,7 @@ async function renderMios(mios: Mio[], styleTable: StyleTable, gfxFiles: string[
<div id="miopreviewplaceholder"></div>
</div>` +
renderWarningContainer(styleTable) +
renderToolBar(mios, styleTable)
await renderToolBar(mios, styleTable)
);
}

Expand Down Expand Up @@ -138,12 +140,15 @@ function renderWarningContainer(styleTable: StyleTable) {
</div>`;
}

function renderToolBar(mios: Mio[], styleTable: StyleTable): string {
async function renderToolBar(mios: Mio[], styleTable: StyleTable): Promise<string> {
const mioSelect = mios.length <= 1 ? '' : `
<label for="mios" class="${styleTable.style('miosLabel', () => `margin-right:5px`)}">${localize('miopreview.mio', 'Military Industrial Organization: ')}</label>
<div class="select-container ${styleTable.style('marginRight10', () => `margin-right:10px`)}">
<select id="mios" class="select multiple-select" tabindex="0" role="combobox">
${mios.map((mio, i) => `<option value="${i}">${mio.id}</option>`).join('')}
${await Promise.all(mios.map(async (mio, i) => {
const localizedText = localisationIndex ? `(${mio.id}) ${await getLocalisedTextQuick(mio.id)}` : mio.id;
return `<option value="${i}">${localizedText}</option>`;
})).then(options => options.join(''))}
</select>
</div>`;

Expand Down Expand Up @@ -183,6 +188,7 @@ async function renderTrait(trait: MioTrait, styleTable: StyleTable, gfxFiles: st

styleTable.style('trait-icon-' + normalizeForStyle('-empty'), () => 'background: grey;');
styleTable.raw(`.${styleTable.name('trait-common')}:hover .${styleTable.name('trait-span')}`, `display:inline-block;`);
styleTable.raw(`.${styleTable.name('trait-common')}:hover .${styleTable.name('trait-span-display')}`, `margin-top: -12px;`);

const traitBg = await getSpriteByGfxName(trait.specialTraitBackground ? 'GFX_country_spefific_org_trait_button' : 'GFX_industrial_org_trait_button', gfxFiles);

Expand Down Expand Up @@ -217,7 +223,7 @@ async function renderTrait(trait: MioTrait, styleTable: StyleTable, gfxFiles: st
start="${trait.token?.start}"
end="${trait.token?.end}"
${file === trait.file ? '' : `file="${trait.file}"`}
title="${trait.id}\n({{position}})">
title="${trait.id}${localisationIndex ? `\n${await getLocalisedTextQuick(trait.name)}` : ''}\n({{position}})">
<div class="
${styleTable.style('effect-host', () => `
text-align: center;
Expand Down Expand Up @@ -251,6 +257,18 @@ async function renderTrait(trait: MioTrait, styleTable: StyleTable, gfxFiles: st
`)}">
${trait.id}
</span>
<br/>
<span
class="${styleTable.style('trait-span-display', () => `
margin: 10px -400px;
margin-top: 84px;
text-align: center;
display: inline-block;
position: relative;
z-index: 5;
`)}">
${localisationIndex ? `${await getLocalisedTextQuick(trait.name)}` : ''}
</span>
</div>
</div>`;
}
Expand Down
19 changes: 14 additions & 5 deletions src/previewdef/technology/contentbuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import { debug } from '../../util/debug';
import { flatMap, sumBy, min, flatten, chain, uniq } from 'lodash';
import { StyleTable } from '../../util/styletable';
import { RenderNodeCommonOptions } from '../../util/hoi4gui/nodecommon';
import { getLocalisedTextQuick } from "../../util/localisationIndex";
import { localisationIndex } from "../../util/featureflags";

const techTreeViewName = 'countrytechtreeview';
const doctrineTreeViewName = 'countrydoctrineview';
Expand Down Expand Up @@ -75,7 +77,7 @@ async function renderTechnologyFolders(technologyTrees: TechnologyTree[], folder
const techFolders = (await Promise.all(folders.map(folder => renderTechnologyFolder(technologyTrees, folder, techTreeViews, containerWindowTypes, styleTable, guiFiles, gfxFiles)))).join('');

return `
${renderFolderSelector(folders, styleTable)}
${await renderFolderSelector(folders, styleTable)}
<div
id="dragger"
class="${styleTable.oneTimeStyle('dragger', () => `
Expand All @@ -99,7 +101,14 @@ async function renderTechnologyFolders(technologyTrees: TechnologyTree[], folder
</div>`;
}

function renderFolderSelector(folders: string[], styleTable: StyleTable): string {
async function renderFolderSelector(folders: string[], styleTable: StyleTable): Promise<string> {
const folderOptions = await Promise.all(
folders.map(async (folder) => {
const localizedText = localisationIndex ? `${await getLocalisedTextQuick(folder)} (${folder})` : folder;
return `<option value="techfolder_${folder}">${localizedText}</option>`;
})
);

return `<div
class="${styleTable.oneTimeStyle('folderSelectorBar', () => `
position: fixed;
Expand All @@ -122,7 +131,7 @@ function renderFolderSelector(folders: string[], styleTable: StyleTable): string
type="text"
class="${styleTable.oneTimeStyle('folderSelector', () => `min-width:200px`)}"
>
${folders.map(folder => `<option value="techfolder_${folder}">${folder}</option>`)}
${folderOptions.join('')}
</select>
</div>
</div>`;
Expand Down Expand Up @@ -371,7 +380,7 @@ async function renderTechnology(
return `<div
start="${technology.token?.start}"
end="${technology.token?.end}"
title="${technology.id}\n(${folder.x}, ${folder.y})"
title="${technology.id}${localisationIndex ? `\n${await getLocalisedTextQuick(technology.id)}` : ''}\n(${folder.x}, ${folder.y})"
class="
navigator
${commonOptions.styleTable.style('navigator', () => `
Expand Down Expand Up @@ -439,7 +448,7 @@ async function renderSubTechnology(
return `<div
start="${subTechnology.token?.start}"
end="${subTechnology.token?.end}"
title="${subTechnology.id}\n(${folder.x}, ${folder.y})"
title="${subTechnology.id}${localisationIndex ? `\n${await getLocalisedTextQuick(subTechnology.id)}` : ''}\n(${folder.x}, ${folder.y})"
class="
navigator
${commonOptions.styleTable.style('navigator', () => `
Expand Down
5 changes: 3 additions & 2 deletions src/util/dependency.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,9 @@ async function scanReferencesForEvents(editor: vscode.TextEditor) {
} catch (e) {
return undefined;
}
}))).filter((e): e is ({ file: string, result: Record<string, Record<string, string>>; }) =>
e && e.result && e.result[language] && typeof e.result[language] === 'object' && !Array.isArray(e.result[language]));
}))).filter((e): e is { file: string, result: Record<string, Record<string, string>> } =>
e !== undefined && e.result !== undefined && typeof e.result[language] === 'object' && !Array.isArray(e.result[language])
);

const existingLocalizationDependency = existingDependency.filter(d => d.type.match(/^locali[zs]ation$/)).map(d => d.path.replace(/\\+/g, '/'));
const moreLocalizationDependencyContent = localizations.filter(lf => {
Expand Down
1 change: 1 addition & 0 deletions src/util/featureflags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ const featureFlags = getConfiguration().featureFlags;
export const useConditionInFocus = !featureFlags.includes('!useConditionInFocus');
export const eventTreePreview = !featureFlags.includes('!eventTreePreview');
export const gfxIndex = featureFlags.includes('gfxIndex');
export const localisationIndex = featureFlags.includes('localisationIndex');
Loading

0 comments on commit 480bae0

Please sign in to comment.