Skip to content

Commit

Permalink
Handle localization in option help messages
Browse files Browse the repository at this point in the history
  • Loading branch information
Gerrit0 committed Feb 18, 2024
1 parent 61a24a0 commit 41a60ee
Show file tree
Hide file tree
Showing 19 changed files with 349 additions and 183 deletions.
7 changes: 6 additions & 1 deletion scripts/generate_options_schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ require("ts-node/register");
const { writeFileSync } = require("fs");
const { addTypeDocOptions } = require("../src/lib/utils/options/sources");
const { ParameterType } = require("../src");
const {
Internationalization,
} = require("../src/lib/internationalization/internationalization");

const IGNORED_OPTIONS = new Set(["help", "version"]);

Expand All @@ -18,13 +21,15 @@ const schema = {
allowTrailingCommas: true,
};

const i18n = new Internationalization(null).createProxy();

addTypeDocOptions({
/** @param {import("../src").DeclarationOption} option */
addDeclaration(option) {
if (IGNORED_OPTIONS.has(option.name)) return;

const data = {
description: option.help,
description: option.help(i18n),
};

const type = option.type ?? ParameterType.String;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ async function run(app: td.Application) {
}

if (app.options.getValue("help")) {
console.log(app.options.getHelp());
console.log(app.options.getHelp(app.i18n));
return ExitCodes.Ok;
}

Expand Down
156 changes: 152 additions & 4 deletions src/lib/internationalization/translatable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,17 +103,16 @@ export const translatable = {
'The --name option was not specified, and no package.json was found. Defaulting project name to "Documentation".',
disable_git_set_but_not_source_link_template: `disableGit is set, but sourceLinkTemplate is not, so source links cannot be produced. Set a sourceLinkTemplate or disableSources to prevent source tracking.`,
disable_git_set_and_git_revision_used: `disableGit is set and sourceLinkTemplate contains {gitRevision}, which will be replaced with an empty string as no revision was provided.`,
provided_git_remote_0_was_invalid: `The provided git remote "{0}" was not valid. Source links will be broken.`,
git_remote_0_not_valid: `The provided git remote "{0}" was not valid. Source links will be broken.`,

// output plugins
custom_css_file_0_does_not_exist: `Custom CSS file at {0} does not exist.`,
unsupported_highlight_language_0_not_highlighted_in_comment_for_1: `Unsupported highlight language {0} will not be highlighted in comment for {1}.`,
could_not_find_file_to_include_0: `Could not find file to include: {0}`,
could_not_find_media_file_0: `Could not find media file: {0}`,
could_not_find_includes_directory:
could_not_find_includes_directory_0:
"Could not find provided includes directory: {0}",
could_not_find_media_directory:
could_not_find_media_directory_0:
"Could not find provided media directory: {0}",

// renderer
Expand Down Expand Up @@ -147,7 +146,7 @@ export const translatable = {
failed_resolve_0_to_file_in_1: `Failed to resolve {0} to a file in {1}`,

option_0_can_only_be_specified_by_config_file: `The '{0}' option can only be specified via a config file.`,
option_0_expected_a_value_but_none_provided: `--{0} expected a value, but none was given as an argument`,
option_0_expected_a_value_but_none_provided: `--{0} expected a value, but none was given as an argument.`,
unknown_option_0_may_have_meant_1: `Unknown option: {0}, you may have meant:\n\t{1}`,

typedoc_key_in_0_ignored: `The 'typedoc' key in {0} was used by the legacy-packages entryPointStrategy and will be ignored.`,
Expand All @@ -165,6 +164,155 @@ export const translatable = {
// plugins
invalid_plugin_0_missing_load_function: `Invalid structure in plugin {0}, no load function found.`,
plugin_0_could_not_be_loaded: `The plugin {0} could not be loaded.`,

// option declarations help
help_options:
"Specify a json option file that should be loaded. If not specified TypeDoc will look for 'typedoc.json' in the current directory.",
help_tsconfig:
"Specify a TypeScript config file that should be loaded. If not specified TypeDoc will look for 'tsconfig.json' in the current directory.",
help_compilerOptions:
"Selectively override the TypeScript compiler options used by TypeDoc.",
help_entryPoints: "The entry points of your documentation.",
help_entryPointStrategy:
"The strategy to be used to convert entry points into documentation modules.",
help_exclude:
"Define patterns to be excluded when expanding a directory that was specified as an entry point.",
help_externalPattern:
"Define patterns for files that should be considered being external.",
help_excludeExternals:
"Prevent externally resolved symbols from being documented.",
help_excludeNotDocumented:
"Prevent symbols that are not explicitly documented from appearing in the results.",
help_excludeNotDocumentedKinds:
"Specify the type of reflections that can be removed by excludeNotDocumented.",
help_excludeInternal:
"Prevent symbols that are marked with @internal from being documented.",
help_excludeCategories:
"Exclude symbols within this category from the documentation.",
help_excludePrivate: "Ignore private variables and methods.",
help_excludeProtected: "Ignore protected variables and methods.",
help_excludeReferences:
"If a symbol is exported multiple times, ignore all but the first export.",
help_externalSymbolLinkMappings:
"Define custom links for symbols not included in the documentation.",
help_media:
"Specify the location with media files that should be copied to the output directory.",
help_includes:
"Specify the location to look for included documents (use [[include:FILENAME]] in comments).",
help_out: "Specify the location the documentation should be written to.",
help_json:
"Specify the location and filename a JSON file describing the project is written to.",
help_pretty:
"Specify whether the output JSON should be formatted with tabs.",
help_emit: "Specify what TypeDoc should emit, 'docs', 'both', or 'none'.",
help_theme: "Specify the theme name to render the documentation with",
help_lightHighlightTheme:
"Specify the code highlighting theme in light mode.",
help_darkHighlightTheme:
"Specify the code highlighting theme in dark mode.",
help_customCss: "Path to a custom CSS file to for the theme to import.",
help_markedOptions:
"Specify the options passed to Marked, the Markdown parser used by TypeDoc.",
help_name:
"Set the name of the project that will be used in the header of the template.",
help_includeVersion: "Add the package version to the project name.",
help_disableSources:
"Disable setting the source of a reflection when documenting it.",
help_sourceLinkTemplate:
"Specify a link template to be used when generating source urls. If not set, will be automatically created using the git remote. Supports {path}, {line}, {gitRevision} placeholders.",
help_gitRevision:
"Use specified revision instead of the last revision for linking to GitHub/Bitbucket source files. Has no effect if disableSources is set.",
help_gitRemote:
"Use the specified remote for linking to GitHub/Bitbucket source files. Has no effect if disableGit or disableSources is set.",
help_disableGit:
"Assume that all can be linked to with the sourceLinkTemplate, sourceLinkTemplate must be set if this is enabled. {path} will be rooted at basePath",
help_basePath:
"Specifies the base path to be used when displaying file paths.",
help_excludeTags:
"Remove the listed block/modifier tags from doc comments.",
help_readme:
"Path to the readme file that should be displayed on the index page. Pass `none` to disable the index page and start the documentation on the globals page.",
help_stripYamlFrontmatter: "Strip YAML frontmatter from markdown files.",
help_cname:
"Set the CNAME file text, it's useful for custom domains on GitHub Pages.",
help_sourceLinkExternal:
"Specifies that source links should be treated as external links to be opened in a new tab.",
help_githubPages:
"Generate a .nojekyll file to prevent 404 errors in GitHub Pages. Defaults to `true`.",
help_sitemapBaseUrl:
"Specify a base URL to be used in generating a sitemap.xml in our output folder. If not specified, no sitemap will be generated.",
help_lang:
"Sets the language to be used in generation and in TypeDoc's messages.",
help_gaID:
"Set the Google Analytics tracking ID and activate tracking code.",
help_hideGenerator: "Do not print the TypeDoc link at the end of the page.",
help_hideParameterTypesInTitle:
"Hides parameter types in signature titles for easier scanning.",
help_cacheBust: "Include the generation time in links to static assets.",
help_searchInComments:
"If set, the search index will also include comments. This will greatly increase the size of the search index.",
help_cleanOutputDir:
"If set, TypeDoc will remove the output directory before writing output.",
help_titleLink:
"Set the link the title in the header points to. Defaults to the documentation homepage.",
help_navigationLinks: "Defines links to be included in the header.",
help_sidebarLinks: "Defines links to be included in the sidebar.",
help_navigationLeaves:
"Branches of the navigation tree which should not be expanded.",
help_navigation: "Determines how the navigation sidebar is organized.",
help_visibilityFilters:
"Specify the default visibility for builtin filters and additional filters according to modifier tags.",
help_searchCategoryBoosts:
"Configure search to give a relevance boost to selected categories",
help_searchGroupBoosts:
'Configure search to give a relevance boost to selected kinds (eg "class")',
help_jsDocCompatibility:
"Sets compatibility options for comment parsing that increase similarity with JSDoc comments.",
help_commentStyle: "Determines how TypeDoc searches for comments.",
help_useTsLinkResolution:
"Use TypeScript's link resolution when determining where @link tags point. This only applies to JSDoc style comments.",
help_preserveLinkText:
"If set, @link tags without link text will use the text content as the link. If not set, will use the target reflection name.",
help_blockTags:
"Block tags which TypeDoc should recognize when parsing comments.",
help_inlineTags:
"Inline tags which TypeDoc should recognize when parsing comments.",
help_modifierTags:
"Modifier tags which TypeDoc should recognize when parsing comments.",
help_categorizeByGroup:
"Specify whether categorization will be done at the group level.",
help_defaultCategory:
"Specify the default category for reflections without a category.",
help_categoryOrder:
"Specify the order in which categories appear. * indicates the relative order for categories not in the list.",
help_groupOrder:
"Specify the order in which groups appear. * indicates the relative order for groups not in the list.",
help_sort: "Specify the sort strategy for documented values.",
help_sortEntryPoints:
"If set, entry points will be subject to the same sorting rules as other reflections.",
help_kindSortOrder:
"Specify the sort order for reflections when 'kind' is specified.",
help_watch: "Watch files for changes and rebuild docs on change.",
help_preserveWatchOutput:
"If set, TypeDoc will not clear the screen between compilation runs.",
help_skipErrorChecking:
"Do not run TypeScript's type checking before generating docs.",
help_help: "Print this message.",
help_version: "Print TypeDoc's version.",
help_showConfig: "Print the resolved configuration and exit.",
help_plugin:
"Specify the npm plugins that should be loaded. Omit to load all installed plugins.",
help_logLevel: "Specify what level of logging should be used.",
help_treatWarningsAsErrors:
"If set, all warnings will be treated as errors.",
help_treatValidationWarningsAsErrors:
"If set, warnings emitted during validation will be treated as errors. This option cannot be used to disable treatWarningsAsErrors for validation warnings.",
help_intentionallyNotExported:
"A list of types which should not produce 'referenced but not documented' warnings.",
help_requiredToBeDocumented:
"A list of reflection kinds that must be documented",
help_validation:
"Specify which validation steps TypeDoc should perform on your generated documentation.",
} as const;

export type BuiltinTranslatableStringArgs = {
Expand Down
4 changes: 2 additions & 2 deletions src/lib/output/themes/MarkedPlugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ export class MarkedPlugin extends ContextAwareRendererComponent {
this.includes = this.includeSource;
} else {
this.application.logger.warn(
this.application.i18n.could_not_find_includes_directory(this.includeSource),
this.application.i18n.could_not_find_includes_directory_0(this.includeSource),
);
}
}
Expand All @@ -146,7 +146,7 @@ export class MarkedPlugin extends ContextAwareRendererComponent {
copySync(this.mediaSource, this.mediaDirectory);
} else {
this.mediaDirectory = undefined;
this.application.logger.warn(this.application.i18n.could_not_find_media_directory(this.mediaSource));
this.application.logger.warn(this.application.i18n.could_not_find_media_directory_0(this.mediaSource));
}
}
}
Expand Down
7 changes: 4 additions & 3 deletions src/lib/utils/general.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import * as Util from "util";
type InternalOnly = true;

/**
* Helper type to convert `T` to `F` if strict mode is on.
* Helper type to convert `T` to `F` if compiling TypeDoc with stricter types.
*
* Can be used in overloads to map a parameter type to `never`. For example, the
* following function will work with any string argument, but to improve the type safety
Expand All @@ -23,14 +23,15 @@ type InternalOnly = true;
*
* ```ts
* function over(flag: 'a' | 'b'): string
* function over(flag: IfStrict<string, never>): string
* // deprecated
* function over(flag: IfInternal<never, string>): string
* function over(flag: string): string { return flag }
* ```
*/
export type IfInternal<T, F> = InternalOnly extends true ? T : F;

/**
* Helper type to convert `T` to `never` if strict mode is on.
* Helper type to convert `T` to `never` if compiling TypeDoc with stricter types.
*
* See {@link IfInternal} for the rationale.
*/
Expand Down
8 changes: 7 additions & 1 deletion src/lib/utils/options/declaration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import type { SortStrategy } from "../sort";
import { isAbsolute, join, resolve } from "path";
import type { EntryPointStrategy } from "../entry-point";
import type { ReflectionKind } from "../../models/reflections/kind";
import type { NeverIfInternal } from "..";
import type { TranslationProxy } from "../../internationalization/internationalization";

/** @enum */
export const EmitStrategy = {
Expand Down Expand Up @@ -313,8 +315,12 @@ export interface DeclarationOptionBase {

/**
* The help text to be displayed to the user when --help is passed.
*
* This may be a string, which will be presented directly, or a function,
* which will be called with an {@link TranslationProxy} so that option help
* can be translated into the user specified locale.
*/
help: string;
help: NeverIfInternal<string> | ((i18n: TranslationProxy) => string);

/**
* The parameter type, used to convert user configuration values into the expected type.
Expand Down
21 changes: 16 additions & 5 deletions src/lib/utils/options/help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
} from "./declaration";
import { getSupportedLanguages } from "../highlighter";
import { BUNDLED_THEMES } from "shiki";
import type { TranslationProxy } from "../../internationalization/internationalization";

export interface ParameterHelp {
names: string[];
Expand All @@ -29,7 +30,10 @@ function hasHint(
* @param scope The scope of the parameters whose help should be returned.
* @returns The columns and lines for the help of the requested parameters.
*/
function getParameterHelp(options: Options): ParameterHelp {
function getParameterHelp(
options: Options,
i18n: TranslationProxy,
): ParameterHelp {
const parameters = options.getDeclarations();
parameters.sort((a, b) =>
a.name.localeCompare(b.name, undefined, { sensitivity: "base" }),
Expand All @@ -50,7 +54,11 @@ function getParameterHelp(options: Options): ParameterHelp {
}

names.push(name);
helps.push(parameter.help);
helps.push(
typeof parameter.help === "string"
? parameter.help
: parameter.help(i18n),
);
margin = Math.max(name.length, margin);
}

Expand Down Expand Up @@ -79,10 +87,13 @@ function toEvenColumns(values: string[], maxLineWidth: number) {
return out;
}

export function getOptionsHelp(options: Options): string {
const output = ["Usage:", " typedoc path/to/entry.ts", "", "Options:"];
export function getOptionsHelp(
options: Options,
i18n: TranslationProxy,
): string {
const output = ["typedoc path/to/entry.ts", "", "Options:"];

const columns = getParameterHelp(options);
const columns = getParameterHelp(options, i18n);
for (let i = 0; i < columns.names.length; i++) {
const usage = columns.names[i];
const description = columns.helps[i];
Expand Down
5 changes: 3 additions & 2 deletions src/lib/utils/options/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
} from "./declaration";
import { addTypeDocOptions } from "./sources";
import { getOptionsHelp } from "./help";
import type { TranslationProxy } from "../../internationalization/internationalization";

/**
* Describes an option reader that discovers user configuration and converts it to the
Expand Down Expand Up @@ -429,8 +430,8 @@ export class Options {
/**
* Get the help message to be displayed to the user if `--help` is passed.
*/
getHelp() {
return getOptionsHelp(this);
getHelp(i18n: TranslationProxy) {
return getOptionsHelp(this, i18n);
}
}

Expand Down
Loading

0 comments on commit 41a60ee

Please sign in to comment.