1
0
mirror of synced 2025-12-19 18:10:59 -05:00

Convert languages.js to TypeScript (#56393)

This commit is contained in:
Kevin Heis
2025-07-09 12:17:13 -07:00
committed by GitHub
parent d01b58210f
commit e6d1d29850
49 changed files with 86 additions and 82 deletions

View File

@@ -2,9 +2,11 @@ import fs from 'fs'
import path from 'path'
import frontmatter from 'gray-matter'
import { languageKeys } from '#src/languages/lib/languages.js'
import { ROOT } from '#src/frame/lib/constants.js'
// Hard-coded language keys to avoid TypeScript import in config file
const languageKeys = ['en', 'es', 'ja', 'pt', 'zh', 'ru', 'fr', 'ko', 'de']
const homepage = path.posix.join(ROOT, 'content/index.md')
const { data } = frontmatter(fs.readFileSync(homepage, 'utf8'))
const productIds = data.children

View File

@@ -17,7 +17,7 @@ import {
} from '@/frame/middleware/set-fastly-surrogate-key.js'
import { readCompressedJsonFileFallbackLazily } from '@/frame/lib/read-json-file.js'
import { archivedCacheControl, languageCacheControl } from '@/frame/middleware/cache-control.js'
import { pathLanguagePrefixed, languagePrefixPathRegex } from '@/languages/lib/languages.js'
import { pathLanguagePrefixed, languagePrefixPathRegex } from '@/languages/lib/languages'
import getRedirect, { splitPathByLanguage } from '@/redirects/lib/get-redirect.js'
import getRemoteJSON from '@/frame/lib/get-remote-json.js'
import { ExtendedRequest } from '@/types'

View File

@@ -30,7 +30,7 @@ import { brotliCompressSync } from 'zlib'
import chalk from 'chalk'
import { program, Option } from 'commander'
import { languageKeys } from '@/languages/lib/languages.js'
import { languageKeys } from '@/languages/lib/languages'
import { loadPages, loadUnversionedTree } from '@/frame/lib/page-data.js'
import { CACHE_FILE_PATH, getPageInfo } from '../middleware/article-pageinfo'

View File

@@ -7,7 +7,7 @@ import { visitParents } from 'unist-util-visit-parents'
import { visit, SKIP } from 'unist-util-visit'
import { remove } from 'unist-util-remove'
import { languageKeys } from '#src/languages/lib/languages.js'
import { languageKeys } from '#src/languages/lib/languages.ts'
import { MARKDOWN_OPTIONS } from '../../content-linter/lib/helpers/unified-formatter-options.js'
const { targetDirectory, removeKeywords } = JSON.parse(

View File

@@ -1,7 +1,7 @@
import { filterTokens } from 'markdownlint-rule-helpers'
import { addFixErrorDetail, getRange } from '../helpers/utils.js'
import { allLanguageKeys } from '#src/languages/lib/languages.js'
import { allLanguageKeys } from '#src/languages/lib/languages.ts'
export const internalLinksNoLang = {
names: ['GHD002', 'internal-links-no-lang'],

View File

@@ -14,7 +14,7 @@ import { defaultConfig } from '../lib/default-markdownlint-options.js'
import { prettyPrintResults } from './pretty-print-results.js'
import { getLintableYml } from '#src/content-linter/lib/helpers/get-lintable-yml.js'
import { printAnnotationResults } from '../lib/helpers/print-annotations.js'
import languages from '#src/languages/lib/languages.js'
import languages from '#src/languages/lib/languages.ts'
program
.description('Run GitHub Docs Markdownlint rules.')

View File

@@ -8,7 +8,7 @@ import walk from 'walk-sync'
import { zip } from 'lodash-es'
import { beforeAll, describe, expect, test } from 'vitest'
import languages from '#src/languages/lib/languages.js'
import languages from '#src/languages/lib/languages.ts'
import { getDiffFiles } from '../lib/diff-files.js'
const __dirname = path.dirname(fileURLToPath(import.meta.url))

View File

@@ -43,7 +43,7 @@ import { writeFileSync, statSync } from 'fs'
import { program, Option } from 'commander'
import { languageKeys } from '@/languages/lib/languages.js'
import { languageKeys } from '@/languages/lib/languages'
import { allVersions } from '@/versions/lib/all-versions'
import { allDocuments, POSSIBLE_FIELDS, type AllDocument } from './lib'

View File

@@ -1,7 +1,7 @@
import { afterAll, beforeAll, describe, expect, test } from 'vitest'
import Page from '#src/frame/lib/page.js'
import languages from '#src/languages/lib/languages.js'
import languages from '#src/languages/lib/languages.ts'
import nonEnterpriseDefaultVersion from '#src/versions/lib/non-enterprise-default-version.js'
import { DataDirectory } from '#src/tests/helpers/data-directory.js'

View File

@@ -1,7 +1,7 @@
import { afterAll, beforeAll, describe, expect, test, vi } from 'vitest'
import { liquid } from '#src/content-render/index.js'
import languages from '#src/languages/lib/languages.js'
import languages from '#src/languages/lib/languages.ts'
import { DataDirectory } from '#src/tests/helpers/data-directory.js'
describe('liquid helper tags', () => {

View File

@@ -5,7 +5,7 @@ import yaml from 'js-yaml'
import matter from 'gray-matter'
import { merge, get } from 'lodash-es'
import languages from '#src/languages/lib/languages.js'
import languages from '#src/languages/lib/languages.ts'
import { correctTranslatedContentStrings } from '#src/languages/lib/correct-translation-content.js'
// If you run `export DEBUG_JIT_DATA_READS=true` in your terminal,

View File

@@ -2,7 +2,7 @@ import fs from 'fs'
import path from 'path'
import chalk from 'chalk'
import languages from '@/languages/lib/languages.js'
import languages from '@/languages/lib/languages'
type Options = {
verbose?: boolean

View File

@@ -38,7 +38,7 @@ import type { Page } from '@/types'
import warmServer from '@/frame/lib/warm-server'
import { getDeepDataByLanguage } from '@/data-directory/lib/get-data.js'
import { getLiquidTokens } from '@/content-linter/lib/helpers/liquid-utils.js'
import languages from '@/languages/lib/languages.js'
import languages from '@/languages/lib/languages'
import { correctTranslatedContentStrings } from '@/languages/lib/correct-translation-content.js'
const EXCEPTIONS = new Set([

View File

@@ -3,7 +3,7 @@ import path from 'path'
import { afterAll, beforeAll, describe, expect, test } from 'vitest'
import languages from '#src/languages/lib/languages.js'
import languages from '#src/languages/lib/languages.ts'
import {
getDataByLanguage,
getDeepDataByLanguage,

View File

@@ -2,7 +2,7 @@ import { expect, test, vi } from 'vitest'
import { get, getDOM } from '@/tests/helpers/e2etest.js'
import { describeIfDocsEarlyAccess } from '@/tests/helpers/conditional-runs.js'
import languages from '@/languages/lib/languages.js'
import languages from '@/languages/lib/languages'
const VALID_EARLY_ACCESS_URI = '/early-access/github/save-time-with-slash-commands'

View File

@@ -1,4 +1,4 @@
import { languageKeys } from '@/languages/lib/languages.js'
import { languageKeys } from '@/languages/lib/languages'
import { allVersionKeys } from '@/versions/lib/all-versions'
import { productIds } from '@/products/lib/all-products'
import { allTools } from '@/tools/lib/all-tools.js'

View File

@@ -1,6 +1,6 @@
import path from 'path'
import languages from '#src/languages/lib/languages.js'
import languages from '#src/languages/lib/languages.ts'
import { allVersions } from '#src/versions/lib/all-versions.ts'
import createTree from './create-tree.js'
import nonEnterpriseDefaultVersion from '#src/versions/lib/non-enterprise-default-version.js'

View File

@@ -2,7 +2,7 @@ import type { NextFunction, Response } from 'express'
import type { ExtendedRequest, Context } from '@/types'
import languages from '@/languages/lib/languages.js'
import languages from '@/languages/lib/languages'
import enterpriseServerReleases from '@/versions/lib/enterprise-server-releases.js'
import { allVersions } from '@/versions/lib/all-versions'
import { productMap } from '@/products/lib/all-products.js'

View File

@@ -3,7 +3,7 @@ import type { Response, NextFunction } from 'express'
import type { ExtendedRequest } from '@/types'
import { getProductGroups } from '@/products/lib/get-product-groups'
import warmServer from '@/frame/lib/warm-server'
import { languageKeys } from '@/languages/lib/languages.js'
import { languageKeys } from '@/languages/lib/languages'
import { allVersionKeys } from '@/versions/lib/all-versions'
const isHomepage = (path: string) => {

View File

@@ -3,7 +3,7 @@ import { existsSync } from 'fs'
import { ROOT } from '#src/frame/lib/constants.js'
import Page from '#src/frame/lib/page.js'
import { languagePrefixPathRegex } from '#src/languages/lib/languages.js'
import { languagePrefixPathRegex } from '#src/languages/lib/languages.ts'
const englishPrefixRegex = /^\/en(\/|$)/
const CONTENT_ROOT = path.join(ROOT, 'content')

View File

@@ -2,7 +2,7 @@ import type { NextFunction, Request, Response } from 'express'
import helmet from 'helmet'
import { isArchivedVersion } from '@/archives/lib/is-archived-version'
import versionSatisfiesRange from '@/versions/lib/version-satisfies-range.js'
import { languagePrefixPathRegex } from '@/languages/lib/languages.js'
import { languagePrefixPathRegex } from '@/languages/lib/languages'
const isDev = process.env.NODE_ENV === 'development'
const GITHUB_DOMAINS = [

View File

@@ -5,7 +5,7 @@ import type { ExtendedRequest } from '@/types'
import { defaultCacheControl } from '@/frame/middleware/cache-control.js'
import catchMiddlewareError from '@/observability/middleware/catch-middleware-error.js'
import statsd from '@/observability/lib/statsd.js'
import languages from '@/languages/lib/languages.js'
import languages from '@/languages/lib/languages'
import { allVersions } from '@/versions/lib/all-versions'
const router = express.Router()

View File

@@ -19,7 +19,7 @@ import path from 'path'
import type { Response, NextFunction } from 'express'
import type { ExtendedRequest, UnversionedTree, SiteTree } from '@/types'
import languages, { languageKeys } from '@/languages/lib/languages.js'
import languages, { languageKeys } from '@/languages/lib/languages'
import createTree from '@/frame/lib/create-tree.js'
import warmServer from '@/frame/lib/warm-server'
import { loadSiteTree, loadPages, loadPageMap } from '@/frame/lib/page-data.js'

View File

@@ -8,7 +8,7 @@ import type { ExtendedRequest } from '@/types'
import FailBot from '@/observability/lib/failbot.js'
import patterns from '@/frame/lib/patterns.js'
import getMiniTocItems from '@/frame/lib/get-mini-toc-items.js'
import { pathLanguagePrefixed } from '@/languages/lib/languages.js'
import { pathLanguagePrefixed } from '@/languages/lib/languages'
import statsd from '@/observability/lib/statsd.js'
import { allVersions } from '@/versions/lib/all-versions'
import { isConnectionDropped } from './halt-on-dropped-connection'

View File

@@ -6,7 +6,7 @@ import { decode } from 'html-entities'
import { chain, pick } from 'lodash-es'
import { loadPages } from '#src/frame/lib/page-data.js'
import libLanguages from '#src/languages/lib/languages.js'
import libLanguages from '#src/languages/lib/languages.ts'
import { liquid } from '#src/content-render/index.js'
import patterns from '#src/frame/lib/patterns.js'
import removeFPTFromPath from '#src/versions/lib/remove-fpt-from-path.js'

View File

@@ -17,7 +17,7 @@ import createApp from '@/frame/lib/app'
import EnterpriseServerReleases from '@/versions/lib/enterprise-server-releases.js'
import loadRedirects from '@/redirects/lib/precompile.js'
import { loadPageMap, loadPages } from '@/frame/lib/page-data.js'
import { languageKeys } from '@/languages/lib/languages.js'
import { languageKeys } from '@/languages/lib/languages'
import { RewriteAssetPathsPlugin } from '@/ghes-releases/scripts/deprecate/rewrite-asset-paths'
const port = '4001'

View File

@@ -3,7 +3,7 @@ import {
readCompressedJsonFileFallback,
} from '#src/frame/lib/read-json-file.js'
import { getAutomatedPageMiniTocItems } from '#src/frame/lib/get-mini-toc-items.js'
import languages from '#src/languages/lib/languages.js'
import languages from '#src/languages/lib/languages.ts'
import { allVersions } from '#src/versions/lib/all-versions.ts'
export const GRAPHQL_DATA_DIR = 'src/graphql/data'

View File

@@ -1,23 +0,0 @@
type Language = {
name: string
nativeName?: string
code: string
hreflang: string
redirectPatterns?: RegExp[]
dir: string
}
type Languages = {
[code: string]: Language
}
export const allLanguageKeys: string[]
export const languageKeys: string[]
export const languagePrefixPathRegex: RegExp
export declare function pathLanguagePrefixed(path: string): boolean
const languages: Languages
export default languages

View File

@@ -6,11 +6,35 @@ import fs from 'fs'
import dotenv from 'dotenv'
import { ROOT, TRANSLATIONS_ROOT, TRANSLATIONS_FIXTURE_ROOT } from '#src/frame/lib/constants.js'
import { ROOT, TRANSLATIONS_ROOT, TRANSLATIONS_FIXTURE_ROOT } from '@/frame/lib/constants'
dotenv.config({ quiet: true })
const possibleEnvVars = {
export interface Language {
name: string
nativeName?: string
code: string
hreflang: string
redirectPatterns?: RegExp[]
dir: string
}
export type LanguageCode = 'en' | 'es' | 'ja' | 'pt' | 'zh' | 'ru' | 'fr' | 'ko' | 'de'
export type LocaleCode =
| 'es-es'
| 'ja-jp'
| 'pt-br'
| 'zh-cn'
| 'ru-ru'
| 'fr-fr'
| 'ko-kr'
| 'de-de'
export interface Languages {
[code: string]: Language
}
const possibleEnvVars: Record<LocaleCode, string | undefined> = {
'es-es': process.env.TRANSLATIONS_ROOT_ES_ES,
'ja-jp': process.env.TRANSLATIONS_ROOT_JA_JP,
'pt-br': process.env.TRANSLATIONS_ROOT_PT_BR,
@@ -21,7 +45,7 @@ const possibleEnvVars = {
'de-de': process.env.TRANSLATIONS_ROOT_DE_DE,
}
function getRoot(languageCode) {
function getRoot(languageCode: string): string {
if (languageCode === 'en') return ROOT
// This one trumps anything else. This makes it possible, and convenient,
@@ -32,7 +56,7 @@ function getRoot(languageCode) {
}
if (languageCode in possibleEnvVars) {
const possibleEnvVar = possibleEnvVars[languageCode]
const possibleEnvVar = possibleEnvVars[languageCode as LocaleCode]
if (possibleEnvVar) {
return possibleEnvVar
}
@@ -44,7 +68,7 @@ function getRoot(languageCode) {
}
// Languages in order of accept-language header frequency
const allLanguages = {
const allLanguages: Languages = {
en: {
name: 'English',
code: 'en',
@@ -112,13 +136,14 @@ const allLanguages = {
dir: getRoot('de-de'),
},
}
// Some markdownlint tests depend on having access to all
// language keys. Not modifying the original object makes
// it possible to export all keys, even when those directories
// don't exist on disk.
Object.freeze(allLanguages)
export const allLanguageKeys = Object.keys(allLanguages)
const languages = { ...allLanguages }
export const allLanguageKeys: string[] = Object.keys(allLanguages)
const languages: Languages = { ...allLanguages }
if (TRANSLATIONS_FIXTURE_ROOT) {
// Keep all languages that have a directory in the fixture root.
@@ -130,7 +155,7 @@ if (TRANSLATIONS_FIXTURE_ROOT) {
} else if (process.env.ENABLED_LANGUAGES) {
if (process.env.ENABLED_LANGUAGES.toLowerCase() !== 'all') {
Object.keys(languages).forEach((code) => {
if (!process.env.ENABLED_LANGUAGES.includes(code)) {
if (!process.env.ENABLED_LANGUAGES!.includes(code)) {
delete languages[code]
}
})
@@ -144,15 +169,15 @@ if (TRANSLATIONS_FIXTURE_ROOT) {
})
}
export const languageKeys = Object.keys(languages)
export const languageKeys: string[] = Object.keys(languages)
export const languagePrefixPathRegex = new RegExp(`^/(${languageKeys.join('|')})(/|$)`)
export const languagePrefixPathRegex: RegExp = new RegExp(`^/(${languageKeys.join('|')})(/|$)`)
/** Return true if the URL is something like /en/foo or /ja but return false
* if it's something like /foo or /foo/bar or /fr (because French (fr)
* is currently not an active language)
*/
export function pathLanguagePrefixed(path) {
export function pathLanguagePrefixed(path: string): boolean {
return languagePrefixPathRegex.test(path)
}

View File

@@ -2,7 +2,7 @@ import type { Request, Response, NextFunction } from 'express'
import parser from 'accept-language-parser'
import type { Language as parserLanguage } from 'accept-language-parser'
import languages, { languageKeys } from '@/languages/lib/languages.js'
import languages, { languageKeys } from '@/languages/lib/languages'
import { USER_LANGUAGE_COOKIE_NAME } from '@/frame/lib/constants.js'
import type { ExtendedRequest, Languages } from '@/types'

View File

@@ -7,7 +7,7 @@ import { TokenizationError } from 'liquidjs'
import walk from 'walk-sync'
import { getLiquidTokens } from '@/content-linter/lib/helpers/liquid-utils.js'
import languages from '@/languages/lib/languages.js'
import languages from '@/languages/lib/languages'
import warmServer from '@/frame/lib/warm-server'
import type { Site } from '@/types'
import { correctTranslatedContentStrings } from '@/languages/lib/correct-translation-content.js'

View File

@@ -1,4 +1,4 @@
import { languageKeys } from '#src/languages/lib/languages.js'
import { languageKeys } from '#src/languages/lib/languages.ts'
import { makeLanguageSurrogateKey } from '#src/frame/middleware/set-fastly-surrogate-key.js'
import purgeEdgeCache from '#src/workflows/purge-edge-cache.ts'

View File

@@ -1,4 +1,4 @@
import languages from '#src/languages/lib/languages.js'
import languages from '#src/languages/lib/languages.ts'
import { describe, expect, test, vi } from 'vitest'
describe('files', () => {

View File

@@ -1,6 +1,6 @@
import { describe, expect, test, vi } from 'vitest'
import { languageKeys } from '@/languages/lib/languages.js'
import { languageKeys } from '@/languages/lib/languages'
import { blockIndex } from '@/frame/middleware/block-robots'
import { get, getDOMCached as getDOM } from '@/tests/helpers/e2etest.js'
import Page from '@/frame/lib/page.js'

View File

@@ -1,6 +1,6 @@
import { describe, expect, test } from 'vitest'
import { languageKeys } from '@/languages/lib/languages.js'
import { languageKeys } from '@/languages/lib/languages'
import { getDOM } from '@/tests/helpers/e2etest.js'
const langs = languageKeys.filter((lang) => lang !== 'en')

View File

@@ -1,6 +1,6 @@
import { describe, expect, test } from 'vitest'
import { get } from '@/tests/helpers/e2etest.js'
import { languageKeys } from '@/languages/lib/languages.js'
import { languageKeys } from '@/languages/lib/languages'
const langs = languageKeys.filter((lang) => lang !== 'en')

View File

@@ -1,6 +1,6 @@
import { describe, expect, test } from 'vitest'
import { languageKeys } from '#src/languages/lib/languages.js'
import { languageKeys } from '#src/languages/lib/languages.ts'
import { get } from '#src/tests/helpers/e2etest.js'
import { USER_LANGUAGE_COOKIE_NAME } from '#src/frame/lib/constants.js'

View File

@@ -1,6 +1,6 @@
import { describe, expect, test } from 'vitest'
import { languageKeys } from '#src/languages/lib/languages'
import { languageKeys } from '#src/languages/lib/languages.ts'
import { get } from '#src/tests/helpers/e2etest.js'
const langs = languageKeys.filter((lang) => lang !== 'en')

View File

@@ -1,4 +1,4 @@
import { languageKeys } from '#src/languages/lib/languages.js'
import { languageKeys } from '@/languages/lib/languages'
import nonEnterpriseDefaultVersion from '#src/versions/lib/non-enterprise-default-version.js'
import { allVersions } from '@/versions/lib/all-versions'
import {

View File

@@ -1,7 +1,7 @@
import type { NextFunction, Response } from 'express'
import patterns from '@/frame/lib/patterns.js'
import { pathLanguagePrefixed } from '@/languages/lib/languages.js'
import { pathLanguagePrefixed } from '@/languages/lib/languages'
import { deprecatedWithFunctionalRedirects } from '@/versions/lib/enterprise-server-releases.js'
import getRedirect from '../lib/get-redirect.js'
import { defaultCacheControl, languageCacheControl } from '@/frame/middleware/cache-control.js'

View File

@@ -1,6 +1,6 @@
import type { NextFunction, Response } from 'express'
import languages from '@/languages/lib/languages.js'
import languages from '@/languages/lib/languages'
import { defaultCacheControl } from '@/frame/middleware/cache-control.js'
import { ExtendedRequest } from '@/types'

View File

@@ -4,7 +4,7 @@ import path from 'path'
import { readCompressedJsonFileFallback } from '#src/frame/lib/read-json-file.js'
import { getAutomatedPageMiniTocItems } from '#src/frame/lib/get-mini-toc-items.js'
import { allVersions, getOpenApiVersion } from '#src/versions/lib/all-versions.ts'
import languages from '#src/languages/lib/languages.js'
import languages from '#src/languages/lib/languages.ts'
export const REST_DATA_DIR = 'src/rest/data'
export const REST_SCHEMA_FILENAME = 'schema.json'

View File

@@ -1,4 +1,4 @@
import languages from '@/languages/lib/languages.js'
import languages from '@/languages/lib/languages'
import { utcTimestamp } from '@/search/lib/helpers/time'
import { allIndexVersionKeys, versionToIndexVersionMap } from '@/search/lib/elasticsearch-versions'

View File

@@ -10,7 +10,7 @@ import { Command, Option } from 'commander'
import chalk from 'chalk'
import dotenv from 'dotenv'
import { languageKeys } from '@/languages/lib/languages.js'
import { languageKeys } from '@/languages/lib/languages'
import { allVersions } from '@/versions/lib/all-versions'
import type { IndicesAnalyzeAnalyzeToken } from '@elastic/elasticsearch/lib/api/types'

View File

@@ -2,7 +2,7 @@ import { program, Option, Command, InvalidArgumentError } from 'commander'
import { errors } from '@elastic/elasticsearch'
import dotenv from 'dotenv'
import { languageKeys } from '@/languages/lib/languages.js'
import { languageKeys } from '@/languages/lib/languages'
import { indexGeneralSearch } from './lib/index-general-search'
import {

View File

@@ -1,6 +1,6 @@
import { Client } from '@elastic/elasticsearch'
import { languageKeys } from '@/languages/lib/languages.js'
import { languageKeys } from '@/languages/lib/languages'
import { getElasticSearchIndex } from '@/search/lib/elasticsearch-indexes'
import { getElasticsearchClient } from '@/search/lib/helpers/get-client'
import {

View File

@@ -4,7 +4,7 @@ import dotenv from 'dotenv'
import boxen from 'boxen'
import { HTTPError } from 'got'
import languages from '@/languages/lib/languages.js'
import languages from '@/languages/lib/languages'
import parsePageSectionsIntoRecords from '@/search/scripts/scrape/lib/parse-page-sections-into-records'
import getPopularPages from '@/search/scripts/scrape/lib/popular-pages'
import domwaiter from '@/search/scripts/scrape/lib/domwaiter'

View File

@@ -1,6 +1,6 @@
import chalk from 'chalk'
import languages from '@/languages/lib/languages.js'
import languages from '@/languages/lib/languages'
import buildRecords from '@/search/scripts/scrape/lib/build-records'
import findIndexablePages from '@/search/scripts/scrape/lib/find-indexable-pages'
import { writeIndexRecords } from '@/search/scripts/scrape/lib/search-index-records'