ALL translations strings shipped with every page (#44284)
Co-authored-by: Robert Sese <734194+rsese@users.noreply.github.com>
This commit is contained in:
@@ -28,7 +28,7 @@ export const DefaultLayout = (props: Props) => {
|
|||||||
fullUrl,
|
fullUrl,
|
||||||
status,
|
status,
|
||||||
} = useMainContext()
|
} = useMainContext()
|
||||||
const { t } = useTranslation(['errors', 'meta', 'scroll_button'])
|
const { t } = useTranslation(['meta', 'scroll_button'])
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const metaDescription = page.introPlainText ? page.introPlainText : t('default_description')
|
const metaDescription = page.introPlainText ? page.introPlainText : t('default_description')
|
||||||
const { languages } = useLanguages()
|
const { languages } = useLanguages()
|
||||||
|
|||||||
@@ -55,6 +55,9 @@ export type ProductTreeNode = {
|
|||||||
childPages: Array<ProductTreeNode>
|
childPages: Array<ProductTreeNode>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UIString = Record<string, string>
|
||||||
|
export type UIStrings = UIString | { [key: string]: UIStrings }
|
||||||
|
|
||||||
export type EnterpriseDeprecation = {
|
export type EnterpriseDeprecation = {
|
||||||
version_was_deprecated: string
|
version_was_deprecated: string
|
||||||
version_will_be_deprecated: string
|
version_will_be_deprecated: string
|
||||||
@@ -67,12 +70,13 @@ type DataReusables = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type DataT = {
|
type DataT = {
|
||||||
ui: Record<string, any>
|
ui: UIStrings
|
||||||
reusables: DataReusables
|
reusables: DataReusables
|
||||||
variables: {
|
variables: {
|
||||||
release_candidate: { version: string }
|
release_candidate: { version: string }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type EnterpriseServerReleases = {
|
type EnterpriseServerReleases = {
|
||||||
isOldestReleaseDeprecated: boolean
|
isOldestReleaseDeprecated: boolean
|
||||||
oldestSupported: string
|
oldestSupported: string
|
||||||
@@ -126,6 +130,38 @@ export type MainContextT = {
|
|||||||
fullUrl: string
|
fullUrl: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write down the namespaces from `data/ui.yml` that are used on all pages,
|
||||||
|
// they will always be available and don't need to be manually added.
|
||||||
|
// Order does not matter on these.
|
||||||
|
const DEFAULT_UI_NAMESPACES = [
|
||||||
|
'header',
|
||||||
|
'search',
|
||||||
|
'survey',
|
||||||
|
'toc',
|
||||||
|
'meta',
|
||||||
|
'scroll_button',
|
||||||
|
'pages',
|
||||||
|
'picker',
|
||||||
|
'footer',
|
||||||
|
'contribution_cta',
|
||||||
|
'support',
|
||||||
|
'rest',
|
||||||
|
]
|
||||||
|
|
||||||
|
export function addUINamespaces(req: any, ui: UIStrings, namespaces: string[]) {
|
||||||
|
const pool = req.context.site.data.ui
|
||||||
|
for (const namespace of namespaces) {
|
||||||
|
if (!(namespace in pool)) {
|
||||||
|
throw new Error(
|
||||||
|
`Invalid namespace "${namespace}". It's not present in data/ui.yml as a namespace. (not one of: ${Object.keys(
|
||||||
|
pool,
|
||||||
|
)})`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
ui[namespace] = pool[namespace]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const getMainContext = async (req: any, res: any): Promise<MainContextT> => {
|
export const getMainContext = async (req: any, res: any): Promise<MainContextT> => {
|
||||||
// Our current translation process adds 'ms.*' frontmatter properties to files
|
// Our current translation process adds 'ms.*' frontmatter properties to files
|
||||||
// it translates including when data/ui.yml is translated. We don't use these
|
// it translates including when data/ui.yml is translated. We don't use these
|
||||||
@@ -140,6 +176,9 @@ export const getMainContext = async (req: any, res: any): Promise<MainContextT>
|
|||||||
}
|
}
|
||||||
const { documentType } = req.context.page
|
const { documentType } = req.context.page
|
||||||
|
|
||||||
|
const ui: UIStrings = {}
|
||||||
|
addUINamespaces(req, ui, DEFAULT_UI_NAMESPACES)
|
||||||
|
|
||||||
// Every product landing page has a listing of all articles.
|
// Every product landing page has a listing of all articles.
|
||||||
// It's used by the <ProductArticlesList> component.
|
// It's used by the <ProductArticlesList> component.
|
||||||
const includeFullProductTree = documentType === 'product'
|
const includeFullProductTree = documentType === 'product'
|
||||||
@@ -171,7 +210,7 @@ export const getMainContext = async (req: any, res: any): Promise<MainContextT>
|
|||||||
isHomepageVersion: req.context.page?.documentType === 'homepage',
|
isHomepageVersion: req.context.page?.documentType === 'homepage',
|
||||||
error: req.context.error ? req.context.error.toString() : '',
|
error: req.context.error ? req.context.error.toString() : '',
|
||||||
data: {
|
data: {
|
||||||
ui: req.context.site.data.ui,
|
ui,
|
||||||
|
|
||||||
reusables,
|
reusables,
|
||||||
|
|
||||||
|
|||||||
@@ -65,8 +65,8 @@ redirect_from:
|
|||||||
- /admin/configuration/configuring-your-enterprise/configuring-data-encryption-for-your-enterprise
|
- /admin/configuration/configuring-your-enterprise/configuring-data-encryption-for-your-enterprise
|
||||||
introLinks:
|
introLinks:
|
||||||
overview: '{% ifversion ghes %}/admin/overview/about-github-enterprise-server{% elsif ghae %}/admin/overview/about-github-ae{% elsif ghec %}/admin/overview/about-github-enterprise-cloud{% endif %}'
|
overview: '{% ifversion ghes %}/admin/overview/about-github-enterprise-server{% elsif ghae %}/admin/overview/about-github-ae{% elsif ghec %}/admin/overview/about-github-enterprise-cloud{% endif %}'
|
||||||
Releases: '{% ifversion ghes %}/admin/all-releases{% endif %}'
|
releases: '{% ifversion ghes %}/admin/all-releases{% endif %}'
|
||||||
Try Enterprise Cloud for free: '{% ifversion ghec %}https://github.com/account/enterprises/new{% endif %}'
|
try_ghec_for_free: '{% ifversion ghec %}https://github.com/account/enterprises/new{% endif %}'
|
||||||
changelog:
|
changelog:
|
||||||
label: enterprise
|
label: enterprise
|
||||||
featuredLinks:
|
featuredLinks:
|
||||||
@@ -127,4 +127,3 @@ children:
|
|||||||
- /release-notes
|
- /release-notes
|
||||||
- /all-releases
|
- /all-releases
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ shortTitle: Migrations
|
|||||||
intro: "If you're moving to {% data variables.product.prodname_dotcom %} from another code hosting platform or moving between {% data variables.product.prodname_dotcom %} products, learn how to use our migration tooling to bring your work with you."
|
intro: "If you're moving to {% data variables.product.prodname_dotcom %} from another code hosting platform or moving between {% data variables.product.prodname_dotcom %} products, learn how to use our migration tooling to bring your work with you."
|
||||||
introLinks:
|
introLinks:
|
||||||
overview: /migrations/overview/about-githubs-migration-tooling
|
overview: /migrations/overview/about-githubs-migration-tooling
|
||||||
Plan your migration: /migrations/overview/planning-your-migration-to-github
|
plan_your_migration: /migrations/overview/planning-your-migration-to-github
|
||||||
featuredLinks:
|
featuredLinks:
|
||||||
startHere:
|
startHere:
|
||||||
- /migrations/importing-source-code/using-github-importer/about-github-importer
|
- /migrations/importing-source-code/using-github-importer/about-github-importer
|
||||||
|
|||||||
42
data/ui.yml
42
data/ui.yml
@@ -23,17 +23,13 @@ picker:
|
|||||||
release_notes:
|
release_notes:
|
||||||
banner_text: GitHub began rolling these changes out to enterprises on
|
banner_text: GitHub began rolling these changes out to enterprises on
|
||||||
search:
|
search:
|
||||||
need_help: Need help?
|
|
||||||
placeholder: Search GitHub Docs
|
|
||||||
search_results_for: Search results for
|
|
||||||
no_content: No content
|
|
||||||
matches_found: Results found
|
|
||||||
matches_displayed: Matches displayed
|
|
||||||
search_error: An error occurred trying to perform the search.
|
|
||||||
description: Enter a search term to find it in the GitHub Docs.
|
description: Enter a search term to find it in the GitHub Docs.
|
||||||
|
placeholder: Search GitHub Docs
|
||||||
label: Search GitHub Docs
|
label: Search GitHub Docs
|
||||||
|
search_results:
|
||||||
|
search_results_for: Search results for
|
||||||
|
matches_displayed: Matches displayed
|
||||||
n_results: '{n} results'
|
n_results: '{n} results'
|
||||||
one_result: 1 result
|
|
||||||
search_validation_error: Validation error with search query
|
search_validation_error: Validation error with search query
|
||||||
homepage:
|
homepage:
|
||||||
explore_by_product: Explore by product
|
explore_by_product: Explore by product
|
||||||
@@ -53,11 +49,6 @@ pages:
|
|||||||
about_versions: About versions
|
about_versions: About versions
|
||||||
permissions_statement: Who can use this feature
|
permissions_statement: Who can use this feature
|
||||||
video_from_transcript: See video for this transcript
|
video_from_transcript: See video for this transcript
|
||||||
errors:
|
|
||||||
oops: Ooops!
|
|
||||||
something_went_wrong: It looks like something went wrong.
|
|
||||||
we_track_errors: We track these errors automatically, but if the problem persists please feel free to contact us.
|
|
||||||
page_doesnt_exist: It looks like this page doesn't exist.
|
|
||||||
support:
|
support:
|
||||||
still_need_help: Still need help?
|
still_need_help: Still need help?
|
||||||
contact_support: Contact support
|
contact_support: Contact support
|
||||||
@@ -97,13 +88,9 @@ parameter_table:
|
|||||||
see_preview_notices: See preview notices
|
see_preview_notices: See preview notices
|
||||||
type: Type
|
type: Type
|
||||||
single_enum_description: Value
|
single_enum_description: Value
|
||||||
products:
|
|
||||||
audit_logs:
|
audit_logs:
|
||||||
action: Action
|
action: Action
|
||||||
description: Description
|
description: Description
|
||||||
button_text:
|
|
||||||
copy_to_clipboard: Copy to clipboard
|
|
||||||
copied: Copied!
|
|
||||||
graphql:
|
graphql:
|
||||||
reference:
|
reference:
|
||||||
implements: <code>{{ GraphQLItemTitle }}</code> Implements
|
implements: <code>{{ GraphQLItemTitle }}</code> Implements
|
||||||
@@ -145,7 +132,7 @@ products:
|
|||||||
additionalPermissions: Additional permissions
|
additionalPermissions: Additional permissions
|
||||||
uat: UAT
|
uat: UAT
|
||||||
iat: IAT
|
iat: IAT
|
||||||
reference:
|
rest_reference:
|
||||||
in: In
|
in: In
|
||||||
description: Description
|
description: Description
|
||||||
notes: Notes
|
notes: Notes
|
||||||
@@ -175,6 +162,9 @@ products:
|
|||||||
ghcli: GitHub CLI
|
ghcli: GitHub CLI
|
||||||
javascript: JavaScript
|
javascript: JavaScript
|
||||||
curl: cURL
|
curl: cURL
|
||||||
|
button_text:
|
||||||
|
copy_to_clipboard: Copy to clipboard
|
||||||
|
copied: Copied!
|
||||||
webhooks:
|
webhooks:
|
||||||
action_type_switch_error: There was an error switching webhook action types.
|
action_type_switch_error: There was an error switching webhook action types.
|
||||||
action_type: Action type
|
action_type: Action type
|
||||||
@@ -202,13 +192,11 @@ product_landing:
|
|||||||
quickstart: Quickstart
|
quickstart: Quickstart
|
||||||
reference: Reference
|
reference: Reference
|
||||||
overview: Overview
|
overview: Overview
|
||||||
|
try_ghec_for_free: Try Enterprise Cloud for free
|
||||||
|
plan_your_migration: Plan your migration
|
||||||
|
releases: Releases
|
||||||
guides: Guides
|
guides: Guides
|
||||||
explore_guides: Explore guides
|
explore_guides: Explore guides
|
||||||
code_examples: Code examples
|
|
||||||
search_code_examples: Search code examples
|
|
||||||
search_results_for: Search results for
|
|
||||||
matches_displayed: Matches displayed
|
|
||||||
show_more: Show more
|
|
||||||
explore_people_and_projects: Explore people and projects
|
explore_people_and_projects: Explore people and projects
|
||||||
sorry: Sorry, there is no result for
|
sorry: Sorry, there is no result for
|
||||||
no_example: It looks like we don't have an example that fits your filter.
|
no_example: It looks like we don't have an example that fits your filter.
|
||||||
@@ -228,9 +216,6 @@ product_landing:
|
|||||||
view: View all
|
view: View all
|
||||||
view_transcript: View video transcript
|
view_transcript: View video transcript
|
||||||
all_docs: 'All {{ title }} docs'
|
all_docs: 'All {{ title }} docs'
|
||||||
code_example:
|
|
||||||
search_button: Search
|
|
||||||
search_examples: 'Search code examples:'
|
|
||||||
product_guides:
|
product_guides:
|
||||||
learning_paths_title: '{{ name }} learning paths'
|
learning_paths_title: '{{ name }} learning paths'
|
||||||
start_path: Start learning path
|
start_path: Start learning path
|
||||||
@@ -258,11 +243,6 @@ learning_track_nav:
|
|||||||
next_guide: Next
|
next_guide: Next
|
||||||
more_guides: More guides →
|
more_guides: More guides →
|
||||||
current_progress: '{i} of {n} in learning path'
|
current_progress: '{i} of {n} in learning path'
|
||||||
toggle_images:
|
|
||||||
off: Images are off, click to show
|
|
||||||
on: Images are on, click to hide
|
|
||||||
hide_single: Hide image
|
|
||||||
show_single: Show image
|
|
||||||
scroll_button:
|
scroll_button:
|
||||||
scroll_to_top: Scroll to top
|
scroll_to_top: Scroll to top
|
||||||
popovers:
|
popovers:
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function GroupedEvents({ auditLogEvents, category }: Props) {
|
export default function GroupedEvents({ auditLogEvents, category }: Props) {
|
||||||
const { t } = useTranslation('products')
|
const { t } = useTranslation('audit_logs')
|
||||||
const eventSlug = slug(category)
|
const eventSlug = slug(category)
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -24,8 +24,8 @@ export default function GroupedEvents({ auditLogEvents, category }: Props) {
|
|||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col">{t('audit_logs.action')}</th>
|
<th scope="col">{t('action')}</th>
|
||||||
<th scope="col">{t('audit_logs.description')}</th>
|
<th scope="col">{t('description')}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
import { GetServerSideProps } from 'next'
|
import { GetServerSideProps } from 'next'
|
||||||
|
|
||||||
import { getMainContext, MainContext, MainContextT } from 'components/context/MainContext'
|
import {
|
||||||
|
addUINamespaces,
|
||||||
|
getMainContext,
|
||||||
|
MainContext,
|
||||||
|
MainContextT,
|
||||||
|
} from 'components/context/MainContext'
|
||||||
import {
|
import {
|
||||||
getAutomatedPageContextFromRequest,
|
getAutomatedPageContextFromRequest,
|
||||||
AutomatedPageContext,
|
AutomatedPageContext,
|
||||||
@@ -50,6 +55,8 @@ export const getServerSideProps: GetServerSideProps<Props> = async (context) =>
|
|||||||
const url = context.req.url
|
const url = context.req.url
|
||||||
|
|
||||||
const mainContext = await getMainContext(req, res)
|
const mainContext = await getMainContext(req, res)
|
||||||
|
addUINamespaces(req, mainContext.data.ui, ['audit_logs'])
|
||||||
|
|
||||||
const { miniTocItems } = getAutomatedPageContextFromRequest(req)
|
const { miniTocItems } = getAutomatedPageContextFromRequest(req)
|
||||||
|
|
||||||
let auditLogEvents = {} as Record<string, Array<AuditLogEventT>>
|
let auditLogEvents = {} as Record<string, Array<AuditLogEventT>>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export function ChildBodyParametersRows({
|
|||||||
childParamsGroups,
|
childParamsGroups,
|
||||||
oneOfObject = false,
|
oneOfObject = false,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const { t } = useTranslation(['parameter_table', 'products'])
|
const { t } = useTranslation(['parameter_table'])
|
||||||
return (
|
return (
|
||||||
<tr className={cx(styles.childBodyParametersRows, 'color-bg-subtle border-top-0')}>
|
<tr className={cx(styles.childBodyParametersRows, 'color-bg-subtle border-top-0')}>
|
||||||
<td className="has-nested-table">
|
<td className="has-nested-table">
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ export function ParameterRow({
|
|||||||
bodyParamExpandCallback,
|
bodyParamExpandCallback,
|
||||||
clickedBodyParameterName,
|
clickedBodyParameterName,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const { t } = useTranslation(['parameter_table', 'products'])
|
const { t } = useTranslation(['parameter_table'])
|
||||||
|
|
||||||
// This will be true if `rowParams` does not have a key called `default`
|
// This will be true if `rowParams` does not have a key called `default`
|
||||||
// and it will be true if it does and its actual value is `undefined`.
|
// and it will be true if it does and its actual value is `undefined`.
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export function ParameterTable({
|
|||||||
clickedBodyParameterName = '',
|
clickedBodyParameterName = '',
|
||||||
variant = 'rest',
|
variant = 'rest',
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const { t } = useTranslation(['parameter_table', 'products'])
|
const { t } = useTranslation(['parameter_table'])
|
||||||
const queryParams = parameters.filter((param) => param.in === 'query')
|
const queryParams = parameters.filter((param) => param.in === 'query')
|
||||||
const pathParams = parameters.filter((param) => param.in === 'path')
|
const pathParams = parameters.filter((param) => param.in === 'path')
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ export function PermissionsList({
|
|||||||
currentVersion === DEFAULT_VERSION ? `/${locale}` : `/${locale}/${currentVersion}`
|
currentVersion === DEFAULT_VERSION ? `/${locale}` : `/${locale}/${currentVersion}`
|
||||||
|
|
||||||
// Translated strings
|
// Translated strings
|
||||||
const { t } = useTranslation('products')
|
const { t } = useTranslation('rest')
|
||||||
const ENDPOINTS_TH = t('rest.overview.permissions.endpoints')
|
const ENDPOINTS_TH = t('rest.overview.permissions.endpoints')
|
||||||
const ACCESS_TH = t('rest.overview.permissions.access')
|
const ACCESS_TH = t('rest.overview.permissions.access')
|
||||||
const TOKENS_TH = t('rest.overview.permissions.tokens')
|
const TOKENS_TH = t('rest.overview.permissions.tokens')
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function Enum({ item }: Props) {
|
export function Enum({ item }: Props) {
|
||||||
const { t } = useTranslation('products')
|
const { t } = useTranslation('graphql')
|
||||||
const heading = t('graphql.reference.values').replace('{{ GraphQLItemTitle }}', item.name)
|
const heading = t('reference.values').replace('{{ GraphQLItemTitle }}', item.name)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GraphqlItem item={item} heading={heading}>
|
<GraphqlItem item={item} heading={heading}>
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function InputObject({ item }: Props) {
|
export function InputObject({ item }: Props) {
|
||||||
const { t } = useTranslation('products')
|
const { t } = useTranslation('graphql')
|
||||||
const heading = t('graphql.reference.input_fields').replace('{{ GraphQLItemTitle }}', item.name)
|
const heading = t('reference.input_fields').replace('{{ GraphQLItemTitle }}', item.name)
|
||||||
return (
|
return (
|
||||||
<GraphqlItem item={item} heading={heading}>
|
<GraphqlItem item={item} heading={heading}>
|
||||||
<Table fields={item.inputFields} />
|
<Table fields={item.inputFields} />
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ type Props = {
|
|||||||
|
|
||||||
export function Interface({ item, objects }: Props) {
|
export function Interface({ item, objects }: Props) {
|
||||||
const { locale } = useRouter()
|
const { locale } = useRouter()
|
||||||
const { t } = useTranslation('products')
|
const { t } = useTranslation('graphql')
|
||||||
const heading = t('graphql.reference.implemented_by').replace('{{ GraphQLItemTitle }}', item.name)
|
const heading = t('reference.implemented_by').replace('{{ GraphQLItemTitle }}', item.name)
|
||||||
const heading2 = t('graphql.reference.fields').replace('{{ GraphQLItemTitle }}', item.name)
|
const heading2 = t('reference.fields').replace('{{ GraphQLItemTitle }}', item.name)
|
||||||
|
|
||||||
const implementedBy = objects.filter(
|
const implementedBy = objects.filter(
|
||||||
(object) =>
|
(object) =>
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ type Props = {
|
|||||||
|
|
||||||
export function Mutation({ item }: Props) {
|
export function Mutation({ item }: Props) {
|
||||||
const { locale } = useRouter()
|
const { locale } = useRouter()
|
||||||
const { t } = useTranslation('products')
|
const { t } = useTranslation('graphql')
|
||||||
const heading = t('graphql.reference.input_fields').replace('{{ GraphQLItemTitle }}', item.name)
|
const heading = t('reference.input_fields').replace('{{ GraphQLItemTitle }}', item.name)
|
||||||
const heading2 = t('graphql.reference.return_fields').replace('{{ GraphQLItemTitle }}', item.name)
|
const heading2 = t('reference.return_fields').replace('{{ GraphQLItemTitle }}', item.name)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GraphqlItem item={item} heading={heading}>
|
<GraphqlItem item={item} heading={heading}>
|
||||||
|
|||||||
@@ -12,11 +12,9 @@ type Props = {
|
|||||||
export function Notice({ item, variant = 'preview' }: Props) {
|
export function Notice({ item, variant = 'preview' }: Props) {
|
||||||
const { locale } = useRouter()
|
const { locale } = useRouter()
|
||||||
|
|
||||||
const { t } = useTranslation('products')
|
const { t } = useTranslation('graphql')
|
||||||
const previewTitle =
|
const previewTitle =
|
||||||
variant === 'preview'
|
variant === 'preview' ? t('reference.preview_notice') : t('reference.deprecation_notice')
|
||||||
? t('graphql.reference.preview_notice')
|
|
||||||
: t('graphql.reference.deprecation_notice')
|
|
||||||
const noticeStyle =
|
const noticeStyle =
|
||||||
variant === 'preview'
|
variant === 'preview'
|
||||||
? 'ghd-spotlight-note color-border-accent-emphasis color-bg-accent'
|
? 'ghd-spotlight-note color-border-accent-emphasis color-bg-accent'
|
||||||
@@ -32,7 +30,7 @@ export function Notice({ item, variant = 'preview' }: Props) {
|
|||||||
<Link href={item.preview.href} locale={locale}>
|
<Link href={item.preview.href} locale={locale}>
|
||||||
{item.preview.title}
|
{item.preview.title}
|
||||||
</Link>
|
</Link>
|
||||||
. {t('graphql.reference.preview_period')}
|
. {t('reference.preview_period')}
|
||||||
</p>
|
</p>
|
||||||
) : item.deprecationReason ? (
|
) : item.deprecationReason ? (
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ type Props = {
|
|||||||
|
|
||||||
export function Object({ item }: Props) {
|
export function Object({ item }: Props) {
|
||||||
const { locale } = useRouter()
|
const { locale } = useRouter()
|
||||||
const { t } = useTranslation('products')
|
const { t } = useTranslation('graphql')
|
||||||
const heading1 = t('graphql.reference.implements').replace('{{ GraphQLItemTitle }}', item.name)
|
const heading1 = t('reference.implements').replace('{{ GraphQLItemTitle }}', item.name)
|
||||||
const heading2 = t('graphql.reference.fields').replace('{{ GraphQLItemTitle }}', item.name)
|
const heading2 = t('reference.fields').replace('{{ GraphQLItemTitle }}', item.name)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GraphqlItem item={item}>
|
<GraphqlItem item={item}>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export function Previews({ schema }: Props) {
|
|||||||
const previews = schema.map((item) => {
|
const previews = schema.map((item) => {
|
||||||
const slugger = new GithubSlugger()
|
const slugger = new GithubSlugger()
|
||||||
const slug = slugger.slug(item.title)
|
const slug = slugger.slug(item.title)
|
||||||
const { t } = useTranslation('products')
|
const { t } = useTranslation('graphql')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cx(styles.markdownBody)} key={slug}>
|
<div className={cx(styles.markdownBody)} key={slug}>
|
||||||
@@ -23,11 +23,11 @@ export function Previews({ schema }: Props) {
|
|||||||
{item.title}
|
{item.title}
|
||||||
</HeadingLink>
|
</HeadingLink>
|
||||||
<p>{item.description}</p>
|
<p>{item.description}</p>
|
||||||
<p>{t('graphql.overview.preview_header')}</p>
|
<p>{t('overview.preview_header')}</p>
|
||||||
<pre>
|
<pre>
|
||||||
<code>{item.accept_header}</code>
|
<code>{item.accept_header}</code>
|
||||||
</pre>
|
</pre>
|
||||||
<p>{t('graphql.overview.preview_schema_members')}:</p>
|
<p>{t('overview.preview_schema_members')}:</p>
|
||||||
<ul>
|
<ul>
|
||||||
{item.toggled_on.map((change) => (
|
{item.toggled_on.map((change) => (
|
||||||
<li key={change + slug}>
|
<li key={change + slug}>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ type Props = {
|
|||||||
|
|
||||||
export function Query({ item }: Props) {
|
export function Query({ item }: Props) {
|
||||||
const { locale } = useRouter()
|
const { locale } = useRouter()
|
||||||
const { t } = useTranslation('products')
|
const { t } = useTranslation('graphql')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GraphqlItem item={item} headingLevel={3}>
|
<GraphqlItem item={item} headingLevel={3}>
|
||||||
@@ -30,10 +30,7 @@ export function Query({ item }: Props) {
|
|||||||
<>
|
<>
|
||||||
<h4
|
<h4
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
__html: t('graphql.reference.arguments').replace(
|
__html: t('reference.arguments').replace('{{ GraphQLItemTitle }}', item.name),
|
||||||
'{{ GraphQLItemTitle }}',
|
|
||||||
item.name,
|
|
||||||
),
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Table fields={item.args} />
|
<Table fields={item.args} />
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ type Props = {
|
|||||||
export function Table({ fields }: Props) {
|
export function Table({ fields }: Props) {
|
||||||
const { locale } = useRouter()
|
const { locale } = useRouter()
|
||||||
|
|
||||||
const { t } = useTranslation('products')
|
const { t } = useTranslation('graphql')
|
||||||
const tableName = t('graphql.reference.name')
|
const tableName = t('reference.name')
|
||||||
const tableDescription = t('graphql.reference.description')
|
const tableDescription = t('reference.description')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<table className="fields width-full table-fixed">
|
<table className="fields width-full table-fixed">
|
||||||
@@ -65,7 +65,7 @@ export function Table({ fields }: Props) {
|
|||||||
<p
|
<p
|
||||||
className="pt-0 mt-0 h5"
|
className="pt-0 mt-0 h5"
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
__html: t('graphql.reference.arguments').replace(
|
__html: t('reference.arguments').replace(
|
||||||
'{{ GraphQLItemTitle }}',
|
'{{ GraphQLItemTitle }}',
|
||||||
field.name,
|
field.name,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ type Props = {
|
|||||||
|
|
||||||
export function Union({ item }: Props) {
|
export function Union({ item }: Props) {
|
||||||
const { locale } = useRouter()
|
const { locale } = useRouter()
|
||||||
const { t } = useTranslation('products')
|
const { t } = useTranslation('graphql')
|
||||||
const heading = t('graphql.reference.possible_types').replace('{{ GraphQLItemTitle }}', item.name)
|
const heading = t('reference.possible_types').replace('{{ GraphQLItemTitle }}', item.name)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GraphqlItem item={item} heading={heading}>
|
<GraphqlItem item={item} heading={heading}>
|
||||||
|
|||||||
@@ -2,7 +2,12 @@ import { GetServerSideProps } from 'next'
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
import { GraphqlPage } from 'src/graphql/components/GraphqlPage'
|
import { GraphqlPage } from 'src/graphql/components/GraphqlPage'
|
||||||
import { MainContextT, MainContext, getMainContext } from 'components/context/MainContext'
|
import {
|
||||||
|
MainContextT,
|
||||||
|
MainContext,
|
||||||
|
getMainContext,
|
||||||
|
addUINamespaces,
|
||||||
|
} from 'components/context/MainContext'
|
||||||
import type { ObjectT, GraphqlT } from 'src/graphql/components/types'
|
import type { ObjectT, GraphqlT } from 'src/graphql/components/types'
|
||||||
import { AutomatedPage } from 'src/automated-pipelines/components/AutomatedPage'
|
import { AutomatedPage } from 'src/automated-pipelines/components/AutomatedPage'
|
||||||
import {
|
import {
|
||||||
@@ -65,9 +70,12 @@ export const getServerSideProps: GetServerSideProps<Props> = async (context) =>
|
|||||||
// Update the existing context to include the miniTocItems from GraphQL
|
// Update the existing context to include the miniTocItems from GraphQL
|
||||||
automatedPageContext.miniTocItems.push(...graphqlMiniTocItems)
|
automatedPageContext.miniTocItems.push(...graphqlMiniTocItems)
|
||||||
|
|
||||||
|
const mainContext = await getMainContext(req, res)
|
||||||
|
addUINamespaces(req, mainContext.data.ui, ['graphql'])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
mainContext: await getMainContext(req, res),
|
mainContext,
|
||||||
automatedPageContext,
|
automatedPageContext,
|
||||||
schema,
|
schema,
|
||||||
language,
|
language,
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
import { GetServerSideProps } from 'next'
|
import { GetServerSideProps } from 'next'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
import { MainContextT, MainContext, getMainContext } from 'components/context/MainContext'
|
import {
|
||||||
|
MainContextT,
|
||||||
|
MainContext,
|
||||||
|
getMainContext,
|
||||||
|
addUINamespaces,
|
||||||
|
} from 'components/context/MainContext'
|
||||||
import { AutomatedPage } from 'src/automated-pipelines/components/AutomatedPage'
|
import { AutomatedPage } from 'src/automated-pipelines/components/AutomatedPage'
|
||||||
import {
|
import {
|
||||||
AutomatedPageContext,
|
AutomatedPageContext,
|
||||||
@@ -47,9 +52,12 @@ export const getServerSideProps: GetServerSideProps<Props> = async (context) =>
|
|||||||
// Update the existing context to include the miniTocItems from GraphQL
|
// Update the existing context to include the miniTocItems from GraphQL
|
||||||
automatedPageContext.miniTocItems.push(...changelogMiniTocItems)
|
automatedPageContext.miniTocItems.push(...changelogMiniTocItems)
|
||||||
|
|
||||||
|
const mainContext = await getMainContext(req, res)
|
||||||
|
addUINamespaces(req, mainContext.data.ui, ['graphql'])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
mainContext: await getMainContext(req, res),
|
mainContext,
|
||||||
automatedPageContext,
|
automatedPageContext,
|
||||||
schema,
|
schema,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import { ArticleCard } from './ArticleCard'
|
|||||||
import { ItemInput } from '@primer/react/lib/deprecated/ActionList/List'
|
import { ItemInput } from '@primer/react/lib/deprecated/ActionList/List'
|
||||||
|
|
||||||
export const ArticleCards = () => {
|
export const ArticleCards = () => {
|
||||||
const { t } = useTranslation('product_guides')
|
const { t, tObject } = useTranslation('product_guides')
|
||||||
const guideTypes: Record<string, string> = t('guide_types')
|
const guideTypes = tObject('guide_types')
|
||||||
const { allTopics, includeGuides } = useProductGuidesContext()
|
const { allTopics, includeGuides } = useProductGuidesContext()
|
||||||
const articleCardRef = useRef<HTMLUListElement>(null)
|
const articleCardRef = useRef<HTMLUListElement>(null)
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ export const ArticleCards = () => {
|
|||||||
? t('guides_found.none')
|
? t('guides_found.none')
|
||||||
: guides.length === 1
|
: guides.length === 1
|
||||||
? t('guides_found.one')
|
? t('guides_found.one')
|
||||||
: t('guides_found.multiple').replace('{n}', guides.length)}
|
: t('guides_found.multiple').replace('{n}', `${guides.length}`)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ export const ArticleCards = () => {
|
|||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
key={card.href + i}
|
key={card.href + i}
|
||||||
card={card}
|
card={card}
|
||||||
typeLabel={guideTypes[card.type]}
|
typeLabel={guideTypes[card.type] as string}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ export const LandingHero = () => {
|
|||||||
href={link}
|
href={link}
|
||||||
className={cx('btn btn-large f4 mt-3 mr-3 ', i === 0 && 'btn-primary')}
|
className={cx('btn btn-large f4 mt-3 mr-3 ', i === 0 && 'btn-primary')}
|
||||||
>
|
>
|
||||||
{t(key) || key}
|
{t(key)}
|
||||||
</FullLink>
|
</FullLink>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import type { GetServerSideProps } from 'next'
|
import type { GetServerSideProps } from 'next'
|
||||||
|
|
||||||
import { MainContextT, MainContext, getMainContext } from 'components/context/MainContext'
|
import {
|
||||||
|
MainContextT,
|
||||||
|
MainContext,
|
||||||
|
getMainContext,
|
||||||
|
addUINamespaces,
|
||||||
|
} from 'components/context/MainContext'
|
||||||
|
|
||||||
import { DefaultLayout } from 'components/DefaultLayout'
|
import { DefaultLayout } from 'components/DefaultLayout'
|
||||||
import { useTranslation } from 'src/languages/components/useTranslation'
|
import { useTranslation } from 'src/languages/components/useTranslation'
|
||||||
@@ -59,11 +64,11 @@ function HomePage(props: HomePageProps) {
|
|||||||
<div className="container-xl">
|
<div className="container-xl">
|
||||||
<div className="gutter gutter-xl-spacious clearfix">
|
<div className="gutter gutter-xl-spacious clearfix">
|
||||||
<div className="col-12 col-lg-6 mb-md-4 mb-lg-0 float-left">
|
<div className="col-12 col-lg-6 mb-md-4 mb-lg-0 float-left">
|
||||||
<ArticleList title={t('toc:getting_started')} articles={gettingStartedLinks} />
|
<ArticleList title={t('getting_started')} articles={gettingStartedLinks} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="col-12 col-lg-6 float-left">
|
<div className="col-12 col-lg-6 float-left">
|
||||||
<ArticleList title={t('toc:popular')} articles={popularLinks} />
|
<ArticleList title={t('popular')} articles={popularLinks} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -76,9 +81,12 @@ export const getServerSideProps: GetServerSideProps<Props> = async (context) =>
|
|||||||
const req = context.req as any
|
const req = context.req as any
|
||||||
const res = context.res as any
|
const res = context.res as any
|
||||||
|
|
||||||
|
const mainContext = await getMainContext(req, res)
|
||||||
|
addUINamespaces(req, mainContext.data.ui, ['homepage', 'product_landing'])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
mainContext: await getMainContext(req, res),
|
mainContext,
|
||||||
productGroups: req.context.productGroups,
|
productGroups: req.context.productGroups,
|
||||||
gettingStartedLinks: req.context.featuredLinks.gettingStarted.map(
|
gettingStartedLinks: req.context.featuredLinks.gettingStarted.map(
|
||||||
({ title, href, intro }: any) => ({ title, href, intro }),
|
({ title, href, intro }: any) => ({ title, href, intro }),
|
||||||
|
|||||||
@@ -7,7 +7,12 @@ import copyCode from 'components/lib/copy-code'
|
|||||||
import toggleAnnotation from 'components/lib/toggle-annotations'
|
import toggleAnnotation from 'components/lib/toggle-annotations'
|
||||||
import wrapCodeTerms from 'components/lib/wrap-code-terms'
|
import wrapCodeTerms from 'components/lib/wrap-code-terms'
|
||||||
|
|
||||||
import { MainContextT, MainContext, getMainContext } from 'components/context/MainContext'
|
import {
|
||||||
|
MainContextT,
|
||||||
|
MainContext,
|
||||||
|
getMainContext,
|
||||||
|
addUINamespaces,
|
||||||
|
} from 'components/context/MainContext'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getProductLandingContextFromRequest,
|
getProductLandingContextFromRequest,
|
||||||
@@ -111,16 +116,28 @@ export const getServerSideProps: GetServerSideProps<Props> = async (context) =>
|
|||||||
}
|
}
|
||||||
const { currentLayoutName, relativePath } = props.mainContext
|
const { currentLayoutName, relativePath } = props.mainContext
|
||||||
|
|
||||||
|
const additionalUINamespaces: string[] = []
|
||||||
|
|
||||||
// This looks a little funky, but it's so we only send one context's data to the client
|
// This looks a little funky, but it's so we only send one context's data to the client
|
||||||
if (currentLayoutName === 'product-landing') {
|
if (currentLayoutName === 'product-landing') {
|
||||||
props.productLandingContext = await getProductLandingContextFromRequest(req)
|
props.productLandingContext = await getProductLandingContextFromRequest(req)
|
||||||
|
additionalUINamespaces.push('product_landing')
|
||||||
} else if (currentLayoutName === 'product-guides') {
|
} else if (currentLayoutName === 'product-guides') {
|
||||||
props.productGuidesContext = getProductGuidesContextFromRequest(req)
|
props.productGuidesContext = getProductGuidesContextFromRequest(req)
|
||||||
|
additionalUINamespaces.push('product_guides')
|
||||||
} else if (relativePath?.endsWith('index.md')) {
|
} else if (relativePath?.endsWith('index.md')) {
|
||||||
props.tocLandingContext = getTocLandingContextFromRequest(req)
|
props.tocLandingContext = getTocLandingContextFromRequest(req)
|
||||||
} else {
|
} else {
|
||||||
|
// All articles that might have hover cards needs this
|
||||||
|
additionalUINamespaces.push('popovers')
|
||||||
|
|
||||||
props.articleContext = getArticleContextFromRequest(req)
|
props.articleContext = getArticleContextFromRequest(req)
|
||||||
|
if (props.articleContext.currentLearningTrack?.trackName) {
|
||||||
|
additionalUINamespaces.push('learning_track_nav')
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addUINamespaces(req, props.mainContext.data.ui, additionalUINamespaces)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props,
|
props,
|
||||||
|
|||||||
@@ -1,41 +1,113 @@
|
|||||||
|
import type { UIStrings } from 'components/context/MainContext'
|
||||||
import { useMainContext } from 'components/context/MainContext'
|
import { useMainContext } from 'components/context/MainContext'
|
||||||
import get from 'lodash/get'
|
|
||||||
|
|
||||||
// The idea of this component is to mimic a popular i18n library (i18next)
|
class TranslationNamespaceError extends Error {}
|
||||||
// so that we can set ourselves up to transition to it (or a similar library) in the future
|
class UngettableError extends Error {}
|
||||||
|
|
||||||
|
// Used to pull translation UI strings from the page props into
|
||||||
|
// React components. When you instantiate the hook you can pass
|
||||||
|
// the name or names of the namespaces you want to use. Then, when
|
||||||
|
// refererring to specific keys you don't have to say the namespace
|
||||||
|
// (or which of the namespaces) you refer to.
|
||||||
|
// Example use:
|
||||||
|
//
|
||||||
|
// const { t, tObject } = useTranslation(['football', 'quiz'])
|
||||||
|
//
|
||||||
|
// return <div>
|
||||||
|
// <b>{t('select')}</b> {/* shorthand now for 'football.select' */}
|
||||||
|
// <select>
|
||||||
|
// {['yes', 'no', 'maybe'].map((answer) => (
|
||||||
|
// <option key={answer} value={answer}>{tObject('choices')[answer]}</option>
|
||||||
|
// )}
|
||||||
|
// </select>
|
||||||
|
// </div>
|
||||||
|
//
|
||||||
|
// You can also use the TemplateStringArray version like:
|
||||||
|
//
|
||||||
|
// <b>{t`select`)}</b>
|
||||||
|
//
|
||||||
|
// Any namespace used when you initialize `useTranslation` that isn't
|
||||||
|
// recognized (prepared in the page props) will throw an error.
|
||||||
|
// And any key not recognized will also throw an error. For example:
|
||||||
|
//
|
||||||
|
// <button>{t('sav_changes')}</button>
|
||||||
|
//
|
||||||
|
// ...will throw because of the typo 'sav_changes' instead of 'save_changes'.
|
||||||
export const useTranslation = (namespaces: string | Array<string>) => {
|
export const useTranslation = (namespaces: string | Array<string>) => {
|
||||||
const { data } = useMainContext()
|
const { data } = useMainContext()
|
||||||
|
|
||||||
// this can eventually be an object constructed from the input namespaces param above, but for now everything is already loaded
|
const loadedData = data.ui
|
||||||
const loadedData: any = data.ui
|
|
||||||
|
const namespacesArray = Array.isArray(namespaces) ? namespaces : [namespaces]
|
||||||
|
|
||||||
|
for (const namespace of namespacesArray) {
|
||||||
|
if (!(namespace in loadedData)) {
|
||||||
|
console.warn(
|
||||||
|
'The following namespaces in data.ui have been loaded: ' +
|
||||||
|
JSON.stringify(Object.keys(loadedData).sort()),
|
||||||
|
)
|
||||||
|
throw new TranslationNamespaceError(
|
||||||
|
`Namespace "${namespace}" not found in data. ` +
|
||||||
|
'Follow the stack trace to see which useTranslation(...) call is ' +
|
||||||
|
'causing this error. If the namespace is present in data/ui.yml ' +
|
||||||
|
'but this error is happening, find the related component ' +
|
||||||
|
'getServerSideProps() it goes through and make sure it calls ' +
|
||||||
|
`addUINamespaces() with "${namespace}".`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function carefulGetWrapper(path: string) {
|
||||||
|
for (const namespace of namespacesArray) {
|
||||||
|
if (!(namespace in loadedData)) {
|
||||||
|
throw new TranslationNamespaceError(`Namespace "${namespace}" not found in data. `)
|
||||||
|
}
|
||||||
|
const deeper = loadedData[namespace]
|
||||||
|
if (typeof deeper === 'string') {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return carefuleGet(deeper, path)
|
||||||
|
} catch (error) {
|
||||||
|
if (!(error instanceof UngettableError)) {
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return carefuleGet(loadedData, path)
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
// The compiled string supports prefixing with a namespace such as `my-namespace:path.to.value`
|
tObject: (strings: TemplateStringsArray | string) => {
|
||||||
|
const key = typeof strings === 'string' ? strings : String.raw(strings)
|
||||||
|
return carefulGetWrapper(key) as UIStrings
|
||||||
|
},
|
||||||
t: (strings: TemplateStringsArray | string, ...values: Array<any>) => {
|
t: (strings: TemplateStringsArray | string, ...values: Array<any>) => {
|
||||||
const key = typeof strings === 'string' ? strings : String.raw(strings, ...values)
|
const key = typeof strings === 'string' ? strings : String.raw(strings, ...values)
|
||||||
|
return carefulGetWrapper(key) as string
|
||||||
const splitKey = key.split(':')
|
|
||||||
if (splitKey.length > 2) {
|
|
||||||
throw new Error('Multiple ":" not allowed in translation lookup path')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (splitKey.length === 2) {
|
|
||||||
const [namespace, path] = splitKey
|
|
||||||
return get(loadedData[namespace], path)
|
|
||||||
}
|
|
||||||
|
|
||||||
const [path] = splitKey
|
|
||||||
if (Array.isArray(namespaces)) {
|
|
||||||
for (const namespace of namespaces) {
|
|
||||||
const val = get(loadedData[namespace], path)
|
|
||||||
if (val !== undefined) {
|
|
||||||
return val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return undefined
|
|
||||||
} else {
|
|
||||||
return get(loadedData[namespaces], path)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function carefuleGet(uiData: UIStrings, dottedPath: string) {
|
||||||
|
const splitPath = dottedPath.split('.')
|
||||||
|
const start = splitPath[0]
|
||||||
|
if (!(start in uiData)) {
|
||||||
|
throw new UngettableError(
|
||||||
|
`Namespace "${start}" not found in loaded data (not one of: ${Object.keys(uiData).sort()})`,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (splitPath.length > 1) {
|
||||||
|
const deeper = uiData[start]
|
||||||
|
if (typeof deeper === 'string') {
|
||||||
|
throw new Error(`Namespace "${start}" is a string, not an object`)
|
||||||
|
}
|
||||||
|
return carefuleGet(deeper, splitPath.slice(1).join('.'))
|
||||||
|
} else {
|
||||||
|
if (!(start in uiData)) {
|
||||||
|
throw new UngettableError(`Key "${start}" not found in loaded data`)
|
||||||
|
}
|
||||||
|
return uiData[start]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ export function LearningTrackCard({ track }: Props) {
|
|||||||
</h2>
|
</h2>
|
||||||
<span className="f5 color-fg-muted">
|
<span className="f5 color-fg-muted">
|
||||||
{t('current_progress')
|
{t('current_progress')
|
||||||
.replace('{n}', numberOfGuides)
|
.replace('{n}', `${numberOfGuides}`)
|
||||||
.replace('{i}', currentGuideIndex + 1)}
|
.replace('{i}', `${currentGuideIndex + 1}`)}
|
||||||
</span>
|
</span>
|
||||||
<hr />
|
<hr />
|
||||||
<span className="h5 color-fg-default">
|
<span className="h5 color-fg-default">
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ type Props = {
|
|||||||
|
|
||||||
export const LearningTrack = ({ track }: Props) => {
|
export const LearningTrack = ({ track }: Props) => {
|
||||||
if (!track) return <div />
|
if (!track) return <div />
|
||||||
const { t } = useTranslation('product_guides')
|
const { t, tObject } = useTranslation('product_guides')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div data-testid="learning-track" className="col-12 col-md-6 my-3 px-4">
|
<div data-testid="learning-track" className="col-12 col-md-6 my-3 px-4">
|
||||||
@@ -32,7 +32,7 @@ export const LearningTrack = ({ track }: Props) => {
|
|||||||
{track.guides.map((guide) => (
|
{track.guides.map((guide) => (
|
||||||
<li key={guide.href + track.trackName}>
|
<li key={guide.href + track.trackName}>
|
||||||
<span className="color-fg-muted mr-2">
|
<span className="color-fg-muted mr-2">
|
||||||
{t('guide_types')[guide.page?.type || '']}
|
{tObject('guide_types')[guide.page?.type || ''] as string}
|
||||||
</span>
|
</span>
|
||||||
<Link
|
<Link
|
||||||
href={`${guide.href}?learn=${track.trackName}&learnProduct=${track.trackProduct}`}
|
href={`${guide.href}?learn=${track.trackName}&learnProduct=${track.trackProduct}`}
|
||||||
|
|||||||
@@ -2,7 +2,12 @@ import { GetServerSideProps } from 'next'
|
|||||||
import { Liquid } from 'liquidjs'
|
import { Liquid } from 'liquidjs'
|
||||||
import pick from 'lodash/pick'
|
import pick from 'lodash/pick'
|
||||||
|
|
||||||
import { MainContextT, MainContext, getMainContext } from 'components/context/MainContext'
|
import {
|
||||||
|
MainContextT,
|
||||||
|
MainContext,
|
||||||
|
getMainContext,
|
||||||
|
addUINamespaces,
|
||||||
|
} from 'components/context/MainContext'
|
||||||
import { DefaultLayout } from 'components/DefaultLayout'
|
import { DefaultLayout } from 'components/DefaultLayout'
|
||||||
import { GHAEReleaseNotes } from 'src/release-notes/components/GHAEReleaseNotes'
|
import { GHAEReleaseNotes } from 'src/release-notes/components/GHAEReleaseNotes'
|
||||||
import { GHESReleaseNotes } from 'src/release-notes/components/GHESReleaseNotes'
|
import { GHESReleaseNotes } from 'src/release-notes/components/GHESReleaseNotes'
|
||||||
@@ -45,9 +50,13 @@ export const getServerSideProps: GetServerSideProps<Props> = async (context) =>
|
|||||||
])
|
])
|
||||||
|
|
||||||
const { latestPatch = '', latestRelease = '' } = req.context
|
const { latestPatch = '', latestRelease = '' } = req.context
|
||||||
|
|
||||||
|
const mainContext = await getMainContext(req, res)
|
||||||
|
addUINamespaces(req, mainContext.data.ui, ['release_notes'])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
mainContext: await getMainContext(req, res),
|
mainContext,
|
||||||
ghesContext:
|
ghesContext:
|
||||||
currentVersion.plan === 'enterprise-server'
|
currentVersion.plan === 'enterprise-server'
|
||||||
? {
|
? {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export const ApiVersionPicker = () => {
|
|||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { currentVersion } = useVersion()
|
const { currentVersion } = useVersion()
|
||||||
const { allVersions } = useMainContext()
|
const { allVersions } = useMainContext()
|
||||||
const { t } = useTranslation(['products'])
|
const { t } = useTranslation('rest')
|
||||||
const basePath = router.asPath.split('#')[0].split('?')[0]
|
const basePath = router.asPath.split('#')[0].split('?')[0]
|
||||||
// Get current date from cookie, query path, or lastly set it to latest rest version date
|
// Get current date from cookie, query path, or lastly set it to latest rest version date
|
||||||
const isValidApiVersion =
|
const isValidApiVersion =
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ const restRepoCategoryExceptionsTitles = {
|
|||||||
|
|
||||||
export const RestBanner = () => {
|
export const RestBanner = () => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { t } = useTranslation('products')
|
const { t } = useTranslation('rest')
|
||||||
// Having a productId === 'rest' and no router.query.category would mean a product landing page like http://docs.github.com/en/rest?apiVersion=2022-08-09
|
// Having a productId === 'rest' and no router.query.category would mean a product landing page like http://docs.github.com/en/rest?apiVersion=2022-08-09
|
||||||
const isRestPage = router.query.productId === 'rest' || router.query.category
|
const isRestPage = router.query.productId === 'rest' || router.query.category
|
||||||
const restPage = router.query.category as string
|
const restPage = router.query.category as string
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ function getLanguageHighlight(selectedLanguage: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function RestCodeSamples({ operation, slug, heading }: Props) {
|
export function RestCodeSamples({ operation, slug, heading }: Props) {
|
||||||
const { t } = useTranslation('products')
|
const { t } = useTranslation(['rest_reference'])
|
||||||
const { isEnterpriseServer } = useVersion()
|
const { isEnterpriseServer } = useVersion()
|
||||||
|
|
||||||
// Refs to track the request example, response example
|
// Refs to track the request example, response example
|
||||||
@@ -264,7 +264,7 @@ export function RestCodeSamples({ operation, slug, heading }: Props) {
|
|||||||
}}
|
}}
|
||||||
href="#"
|
href="#"
|
||||||
>
|
>
|
||||||
{t(`rest.reference.code_sample_options.${optionKey}`)}
|
{t(`code_sample_options.${optionKey}`)}
|
||||||
</TabNav.Link>
|
</TabNav.Link>
|
||||||
))}
|
))}
|
||||||
</TabNav>
|
</TabNav>
|
||||||
@@ -311,7 +311,7 @@ export function RestCodeSamples({ operation, slug, heading }: Props) {
|
|||||||
<h4
|
<h4
|
||||||
className="mt-5 mb-2 h5"
|
className="mt-5 mb-2 h5"
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
__html: displayedExample.response.description || t('rest.reference.response'),
|
__html: displayedExample.response.description || t('response'),
|
||||||
}}
|
}}
|
||||||
></h4>
|
></h4>
|
||||||
<div className="border rounded-1">
|
<div className="border rounded-1">
|
||||||
@@ -335,7 +335,7 @@ export function RestCodeSamples({ operation, slug, heading }: Props) {
|
|||||||
}}
|
}}
|
||||||
href="#"
|
href="#"
|
||||||
>
|
>
|
||||||
{t(`rest.reference.response_options.${optionKey}`)}
|
{t(`response_options.${optionKey}`)}
|
||||||
</TabNav.Link>
|
</TabNav.Link>
|
||||||
))}
|
))}
|
||||||
</TabNav>
|
</TabNav>
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ const DEFAULT_ACCEPT_HEADER = {
|
|||||||
|
|
||||||
export function RestOperation({ operation }: Props) {
|
export function RestOperation({ operation }: Props) {
|
||||||
const titleSlug = slug(operation.title)
|
const titleSlug = slug(operation.title)
|
||||||
const { t } = useTranslation('products')
|
const { t } = useTranslation('rest_reference')
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const headers = [DEFAULT_ACCEPT_HEADER]
|
const headers = [DEFAULT_ACCEPT_HEADER]
|
||||||
@@ -48,10 +48,8 @@ export function RestOperation({ operation }: Props) {
|
|||||||
<CheckCircleFillIcon size={16} />
|
<CheckCircleFillIcon size={16} />
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
{t('rest.reference.works_with') + ' '}
|
{t('works_with') + ' '}
|
||||||
<Link className="" href={`/${router.locale}/developers/apps`}>
|
<Link href={`/${router.locale}/developers/apps`}>GitHub Apps</Link>
|
||||||
GitHub Apps
|
|
||||||
</Link>
|
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@@ -66,10 +64,7 @@ export function RestOperation({ operation }: Props) {
|
|||||||
<ParameterTable
|
<ParameterTable
|
||||||
slug={titleSlug}
|
slug={titleSlug}
|
||||||
numPreviews={numPreviews}
|
numPreviews={numPreviews}
|
||||||
heading={t('rest.reference.parameters').replace(
|
heading={t('parameters').replace('{{ RESTOperationTitle }}', operation.title)}
|
||||||
'{{ RESTOperationTitle }}',
|
|
||||||
operation.title,
|
|
||||||
)}
|
|
||||||
headers={headers}
|
headers={headers}
|
||||||
parameters={operation.parameters}
|
parameters={operation.parameters}
|
||||||
bodyParameters={operation.bodyParameters}
|
bodyParameters={operation.bodyParameters}
|
||||||
@@ -80,10 +75,7 @@ export function RestOperation({ operation }: Props) {
|
|||||||
<RestStatusCodes
|
<RestStatusCodes
|
||||||
statusCodes={operation.statusCodes}
|
statusCodes={operation.statusCodes}
|
||||||
slug={titleSlug}
|
slug={titleSlug}
|
||||||
heading={t('rest.reference.http_status_code').replace(
|
heading={t('http_status_code').replace('{{ RESTOperationTitle }}', operation.title)}
|
||||||
'{{ RESTOperationTitle }}',
|
|
||||||
operation.title,
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -95,10 +87,7 @@ export function RestOperation({ operation }: Props) {
|
|||||||
<RestCodeSamples
|
<RestCodeSamples
|
||||||
operation={operation}
|
operation={operation}
|
||||||
slug={titleSlug}
|
slug={titleSlug}
|
||||||
heading={t('rest.reference.code_samples').replace(
|
heading={t('code_samples').replace('{{ RESTOperationTitle }}', operation.title)}
|
||||||
'{{ RESTOperationTitle }}',
|
|
||||||
operation.title,
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -108,14 +97,8 @@ export function RestOperation({ operation }: Props) {
|
|||||||
previews={operation.previews}
|
previews={operation.previews}
|
||||||
heading={
|
heading={
|
||||||
operation.previews.length > 1
|
operation.previews.length > 1
|
||||||
? `${t('rest.reference.preview_notices').replace(
|
? `${t('preview_notices').replace('{{ RESTOperationTitle }}', operation.title)}`
|
||||||
'{{ RESTOperationTitle }}',
|
: `${t('preview_notice').replace('{{ RESTOperationTitle }}', operation.title)}`
|
||||||
operation.title,
|
|
||||||
)}`
|
|
||||||
: `${t('rest.reference.preview_notice').replace(
|
|
||||||
'{{ RESTOperationTitle }}',
|
|
||||||
operation.title,
|
|
||||||
)}`
|
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function RestStatusCodes({ statusCodes, slug, heading }: Props) {
|
export function RestStatusCodes({ statusCodes, slug, heading }: Props) {
|
||||||
const { t } = useTranslation('products')
|
const { t } = useTranslation('rest_reference')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -19,8 +19,8 @@ export function RestStatusCodes({ statusCodes, slug, heading }: Props) {
|
|||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr className="text-left">
|
<tr className="text-left">
|
||||||
<th>{t('rest.reference.status_code')}</th>
|
<th>{t('status_code')}</th>
|
||||||
<th>{t('rest.reference.description')}</th>
|
<th>{t('description')}</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
import { GetServerSideProps } from 'next'
|
import { GetServerSideProps } from 'next'
|
||||||
import { Operation } from 'src/rest/components/types'
|
import { Operation } from 'src/rest/components/types'
|
||||||
import { RestReferencePage } from 'src/rest/components/RestReferencePage'
|
import { RestReferencePage } from 'src/rest/components/RestReferencePage'
|
||||||
import { getMainContext, MainContext, MainContextT } from 'components/context/MainContext'
|
import {
|
||||||
|
addUINamespaces,
|
||||||
|
getMainContext,
|
||||||
|
MainContext,
|
||||||
|
MainContextT,
|
||||||
|
} from 'components/context/MainContext'
|
||||||
import {
|
import {
|
||||||
AutomatedPageContext,
|
AutomatedPageContext,
|
||||||
AutomatedPageContextT,
|
AutomatedPageContextT,
|
||||||
@@ -77,10 +82,13 @@ export const getServerSideProps: GetServerSideProps<Props> = async (context) =>
|
|||||||
restOperationsMiniTocItems && miniTocItems.push(...restOperationsMiniTocItems)
|
restOperationsMiniTocItems && miniTocItems.push(...restOperationsMiniTocItems)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const mainContext = await getMainContext(req, res)
|
||||||
|
addUINamespaces(req, mainContext.data.ui, ['parameter_table', 'rest_reference'])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
restOperations,
|
restOperations,
|
||||||
mainContext: await getMainContext(req, res),
|
mainContext,
|
||||||
automatedPageContext: getAutomatedPageContextFromRequest(req),
|
automatedPageContext: getAutomatedPageContextFromRequest(req),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,12 +45,12 @@ function SearchResultHits({ hits, search }: { hits: SearchResultHitT[]; search:
|
|||||||
}
|
}
|
||||||
|
|
||||||
function NoSearchResults() {
|
function NoSearchResults() {
|
||||||
const { t } = useTranslation('search')
|
const { t } = useTranslation('search_results')
|
||||||
return (
|
return (
|
||||||
<div className="d-flex flex-items-center flex-column my-6 border rounded-2">
|
<div className="d-flex flex-items-center flex-column my-6 border rounded-2">
|
||||||
<div className="d-flex flex-items-center flex-column p-4">
|
<div className="d-flex flex-items-center flex-column p-4">
|
||||||
<SearchIcon size={24} />
|
<SearchIcon size={24} />
|
||||||
<Text className="f2 mt-3">{t('n_results').replace('{n}', 0)}</Text>
|
<Text className="f2 mt-3">{t('n_results').replace('{n}', '0')}</Text>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function ValidationErrors({ errors }: Props) {
|
export function ValidationErrors({ errors }: Props) {
|
||||||
const { t } = useTranslation('search')
|
const { t } = useTranslation('search_results')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ type Props = {
|
|||||||
|
|
||||||
export function Search({ search }: Props) {
|
export function Search({ search }: Props) {
|
||||||
const { formatInteger } = useNumberFormatter()
|
const { formatInteger } = useNumberFormatter()
|
||||||
const { t } = useTranslation('search')
|
const { t } = useTranslation('search_results')
|
||||||
const { currentVersion } = useVersion()
|
const { currentVersion } = useVersion()
|
||||||
|
|
||||||
const { query } = search.search
|
const { query } = search.search
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
import type { GetServerSideProps } from 'next'
|
import type { GetServerSideProps } from 'next'
|
||||||
|
|
||||||
import { MainContextT, MainContext, getMainContext } from 'components/context/MainContext'
|
import {
|
||||||
|
MainContextT,
|
||||||
|
MainContext,
|
||||||
|
getMainContext,
|
||||||
|
addUINamespaces,
|
||||||
|
} from 'components/context/MainContext'
|
||||||
import { DefaultLayout } from 'components/DefaultLayout'
|
import { DefaultLayout } from 'components/DefaultLayout'
|
||||||
import type { SearchT } from 'src/search/components/types'
|
import type { SearchT } from 'src/search/components/types'
|
||||||
import { Search } from 'src/search/components/index'
|
import { Search } from 'src/search/components/index'
|
||||||
@@ -37,6 +42,7 @@ export const getServerSideProps: GetServerSideProps<Props> = async (context) =>
|
|||||||
}
|
}
|
||||||
|
|
||||||
const mainContext = await getMainContext(req, res)
|
const mainContext = await getMainContext(req, res)
|
||||||
|
addUINamespaces(req, mainContext.data.ui, ['search_results'])
|
||||||
|
|
||||||
if (!req.context.search) {
|
if (!req.context.search) {
|
||||||
// This should have been done by the middleware.
|
// This should have been done by the middleware.
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import { useRouter } from 'next/router'
|
|||||||
import { slug } from 'github-slugger'
|
import { slug } from 'github-slugger'
|
||||||
import cx from 'classnames'
|
import cx from 'classnames'
|
||||||
|
|
||||||
import { useMainContext } from 'components/context/MainContext'
|
|
||||||
import { useVersion } from 'src/versions/components/useVersion'
|
import { useVersion } from 'src/versions/components/useVersion'
|
||||||
import { HeadingLink } from 'components/article/HeadingLink'
|
import { HeadingLink } from 'components/article/HeadingLink'
|
||||||
import { useTranslation } from 'src/languages/components/useTranslation'
|
import { useTranslation } from 'src/languages/components/useTranslation'
|
||||||
@@ -48,15 +47,14 @@ function isScrapedGhesVersion(version: ReturnType<typeof useVersion>) {
|
|||||||
export function Webhook({ webhook }: Props) {
|
export function Webhook({ webhook }: Props) {
|
||||||
// Get version for requests to switch webhook action type
|
// Get version for requests to switch webhook action type
|
||||||
const version = useVersion()
|
const version = useVersion()
|
||||||
const { t } = useTranslation('products')
|
const { t, tObject } = useTranslation('webhooks')
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const context = useMainContext()
|
|
||||||
// Get more user friendly language for the different availability options in
|
// Get more user friendly language for the different availability options in
|
||||||
// the webhook schema (we can't change it directly in the schema). Note that
|
// the webhook schema (we can't change it directly in the schema). Note that
|
||||||
// we specifically don't want to translate these strings with useTranslation()
|
// we specifically don't want to translate these strings with useTranslation()
|
||||||
// like we usually do with strings from data/ui.yml.
|
// like we usually do with strings from data/ui.yml.
|
||||||
const rephraseAvailability = context.data.ui.products.webhooks.rephrase_availability
|
const rephraseAvailability = tObject('rephrase_availability')
|
||||||
|
|
||||||
// The param that was clicked so we can expand its property <details> element
|
// The param that was clicked so we can expand its property <details> element
|
||||||
const [clickedBodyParameterName, setClickedBodyParameterName] = useState<undefined | string>('')
|
const [clickedBodyParameterName, setClickedBodyParameterName] = useState<undefined | string>('')
|
||||||
@@ -150,10 +148,7 @@ export function Webhook({ webhook }: Props) {
|
|||||||
<div dangerouslySetInnerHTML={{ __html: currentWebhookAction.summaryHtml }}></div>
|
<div dangerouslySetInnerHTML={{ __html: currentWebhookAction.summaryHtml }}></div>
|
||||||
<h3
|
<h3
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
__html: t('webhooks.availability').replace(
|
__html: t('availability').replace('{{ WebhookName }}', currentWebhookAction.category),
|
||||||
'{{ WebhookName }}',
|
|
||||||
currentWebhookAction.category,
|
|
||||||
),
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<ul>
|
<ul>
|
||||||
@@ -169,7 +164,9 @@ export function Webhook({ webhook }: Props) {
|
|||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<li key={`availability-${availability}`}>
|
<li key={`availability-${availability}`}>
|
||||||
{rephraseAvailability[availability] ?? availability}
|
{availability in rephraseAvailability
|
||||||
|
? (rephraseAvailability[availability] as string)
|
||||||
|
: availability}
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -177,7 +174,7 @@ export function Webhook({ webhook }: Props) {
|
|||||||
</ul>
|
</ul>
|
||||||
<h3
|
<h3
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
__html: t('webhooks.webhook_payload_object').replace(
|
__html: t('webhook_payload_object').replace(
|
||||||
'{{ WebhookName }}',
|
'{{ WebhookName }}',
|
||||||
currentWebhookAction.category,
|
currentWebhookAction.category,
|
||||||
),
|
),
|
||||||
@@ -185,7 +182,7 @@ export function Webhook({ webhook }: Props) {
|
|||||||
/>
|
/>
|
||||||
{error && (
|
{error && (
|
||||||
<Flash className="mb-5" variant="danger">
|
<Flash className="mb-5" variant="danger">
|
||||||
<p>{t('webhooks.action_type_switch_error')}</p>
|
<p>{t('action_type_switch_error')}</p>
|
||||||
<p>
|
<p>
|
||||||
<code className="f6" style={{ background: 'none' }}>
|
<code className="f6" style={{ background: 'none' }}>
|
||||||
{error.toString()}
|
{error.toString()}
|
||||||
@@ -201,8 +198,7 @@ export function Webhook({ webhook }: Props) {
|
|||||||
aria-label="Select a webhook action type"
|
aria-label="Select a webhook action type"
|
||||||
className="text-normal"
|
className="text-normal"
|
||||||
>
|
>
|
||||||
{t('webhooks.action_type')}:{' '}
|
{t('action_type')}: <span className="text-bold">{currentWebhookActionType}</span>
|
||||||
<span className="text-bold">{currentWebhookActionType}</span>
|
|
||||||
</ActionMenu.Button>
|
</ActionMenu.Button>
|
||||||
<ActionMenu.Overlay>
|
<ActionMenu.Overlay>
|
||||||
<ActionList selectionVariant="single">
|
<ActionList selectionVariant="single">
|
||||||
@@ -240,11 +236,8 @@ export function Webhook({ webhook }: Props) {
|
|||||||
|
|
||||||
{webhook.data.payloadExample && (
|
{webhook.data.payloadExample && (
|
||||||
<>
|
<>
|
||||||
<h3>{t('webhooks.webhook_payload_example')}</h3>
|
<h3>{t('webhook_payload_example')}</h3>
|
||||||
<div
|
<div className={cx(styles.payloadExample, 'border rounded-1 my-0')} data-highlight="json">
|
||||||
className={cx(styles.payloadExample, 'border rounded-1 my-0')}
|
|
||||||
data-highlight={'json'}
|
|
||||||
>
|
|
||||||
<code>{JSON.stringify(webhook.data.payloadExample, null, 2)}</code>
|
<code>{JSON.stringify(webhook.data.payloadExample, null, 2)}</code>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -2,7 +2,12 @@ import { GetServerSideProps } from 'next'
|
|||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
|
|
||||||
import { getMainContext, MainContext, MainContextT } from 'components/context/MainContext'
|
import {
|
||||||
|
addUINamespaces,
|
||||||
|
getMainContext,
|
||||||
|
MainContext,
|
||||||
|
MainContextT,
|
||||||
|
} from 'components/context/MainContext'
|
||||||
import {
|
import {
|
||||||
getAutomatedPageContextFromRequest,
|
getAutomatedPageContextFromRequest,
|
||||||
AutomatedPageContext,
|
AutomatedPageContext,
|
||||||
@@ -77,6 +82,7 @@ export const getServerSideProps: GetServerSideProps<Props> = async (context) =>
|
|||||||
const res = context.res as object
|
const res = context.res as object
|
||||||
const currentVersion = context.query.versionId as string
|
const currentVersion = context.query.versionId as string
|
||||||
const mainContext = await getMainContext(req, res)
|
const mainContext = await getMainContext(req, res)
|
||||||
|
addUINamespaces(req, mainContext.data.ui, ['parameter_table', 'webhooks'])
|
||||||
const { miniTocItems } = getAutomatedPageContextFromRequest(req)
|
const { miniTocItems } = getAutomatedPageContextFromRequest(req)
|
||||||
|
|
||||||
// Get data for initial webhooks page (i.e. only 1 action type per webhook and
|
// Get data for initial webhooks page (i.e. only 1 action type per webhook and
|
||||||
|
|||||||
42
tests/fixtures/data/ui.yml
vendored
42
tests/fixtures/data/ui.yml
vendored
@@ -23,17 +23,13 @@ picker:
|
|||||||
release_notes:
|
release_notes:
|
||||||
banner_text: GitHub began rolling these changes out to enterprises on
|
banner_text: GitHub began rolling these changes out to enterprises on
|
||||||
search:
|
search:
|
||||||
need_help: Need help?
|
|
||||||
placeholder: Search GitHub Docs
|
|
||||||
search_results_for: Search results for
|
|
||||||
no_content: No content
|
|
||||||
matches_found: Results found
|
|
||||||
matches_displayed: Matches displayed
|
|
||||||
search_error: An error occurred trying to perform the search.
|
|
||||||
description: Enter a search term to find it in the GitHub Docs.
|
description: Enter a search term to find it in the GitHub Docs.
|
||||||
|
placeholder: Search GitHub Docs
|
||||||
label: Search GitHub Docs
|
label: Search GitHub Docs
|
||||||
|
search_results:
|
||||||
|
search_results_for: Search results for
|
||||||
|
matches_displayed: Matches displayed
|
||||||
n_results: '{n} results'
|
n_results: '{n} results'
|
||||||
one_result: 1 result
|
|
||||||
search_validation_error: Validation error with search query
|
search_validation_error: Validation error with search query
|
||||||
homepage:
|
homepage:
|
||||||
explore_by_product: Explore by product
|
explore_by_product: Explore by product
|
||||||
@@ -53,11 +49,6 @@ pages:
|
|||||||
about_versions: About versions
|
about_versions: About versions
|
||||||
permissions_statement: Who can use this feature
|
permissions_statement: Who can use this feature
|
||||||
video_from_transcript: See video for this transcript
|
video_from_transcript: See video for this transcript
|
||||||
errors:
|
|
||||||
oops: Ooops!
|
|
||||||
something_went_wrong: It looks like something went wrong.
|
|
||||||
we_track_errors: We track these errors automatically, but if the problem persists please feel free to contact us.
|
|
||||||
page_doesnt_exist: It looks like this page doesn't exist.
|
|
||||||
support:
|
support:
|
||||||
still_need_help: Still need help?
|
still_need_help: Still need help?
|
||||||
contact_support: Contact support
|
contact_support: Contact support
|
||||||
@@ -97,13 +88,9 @@ parameter_table:
|
|||||||
see_preview_notices: See preview notices
|
see_preview_notices: See preview notices
|
||||||
type: Type
|
type: Type
|
||||||
single_enum_description: Value
|
single_enum_description: Value
|
||||||
products:
|
|
||||||
audit_logs:
|
audit_logs:
|
||||||
action: Action
|
action: Action
|
||||||
description: Description
|
description: Description
|
||||||
button_text:
|
|
||||||
copy_to_clipboard: Copy to clipboard
|
|
||||||
copied: Copied!
|
|
||||||
graphql:
|
graphql:
|
||||||
reference:
|
reference:
|
||||||
implements: <code>{{ GraphQLItemTitle }}</code> Implements
|
implements: <code>{{ GraphQLItemTitle }}</code> Implements
|
||||||
@@ -145,7 +132,7 @@ products:
|
|||||||
additionalPermissions: Additional permissions
|
additionalPermissions: Additional permissions
|
||||||
uat: UAT
|
uat: UAT
|
||||||
iat: IAT
|
iat: IAT
|
||||||
reference:
|
rest_reference:
|
||||||
in: In
|
in: In
|
||||||
description: Description
|
description: Description
|
||||||
notes: Notes
|
notes: Notes
|
||||||
@@ -175,6 +162,9 @@ products:
|
|||||||
ghcli: GitHub CLI
|
ghcli: GitHub CLI
|
||||||
javascript: JavaScript
|
javascript: JavaScript
|
||||||
curl: cURL
|
curl: cURL
|
||||||
|
button_text:
|
||||||
|
copy_to_clipboard: Copy to clipboard
|
||||||
|
copied: Copied!
|
||||||
webhooks:
|
webhooks:
|
||||||
action_type_switch_error: There was an error switching webhook action types.
|
action_type_switch_error: There was an error switching webhook action types.
|
||||||
action_type: Action type
|
action_type: Action type
|
||||||
@@ -202,13 +192,11 @@ product_landing:
|
|||||||
quickstart: Quickstart
|
quickstart: Quickstart
|
||||||
reference: Reference
|
reference: Reference
|
||||||
overview: Overview
|
overview: Overview
|
||||||
|
try_ghec_for_free: Try Enterprise Cloud for free
|
||||||
|
plan_your_migration: Plan your migration
|
||||||
|
releases: Releases
|
||||||
guides: Guides
|
guides: Guides
|
||||||
explore_guides: Explore guides
|
explore_guides: Explore guides
|
||||||
code_examples: Code examples
|
|
||||||
search_code_examples: Search code examples
|
|
||||||
search_results_for: Search results for
|
|
||||||
matches_displayed: Matches displayed
|
|
||||||
show_more: Show more
|
|
||||||
explore_people_and_projects: Explore people and projects
|
explore_people_and_projects: Explore people and projects
|
||||||
sorry: Sorry, there is no result for
|
sorry: Sorry, there is no result for
|
||||||
no_example: It looks like we don't have an example that fits your filter.
|
no_example: It looks like we don't have an example that fits your filter.
|
||||||
@@ -228,9 +216,6 @@ product_landing:
|
|||||||
view: View all
|
view: View all
|
||||||
view_transcript: View video transcript
|
view_transcript: View video transcript
|
||||||
all_docs: 'All {{ title }} docs'
|
all_docs: 'All {{ title }} docs'
|
||||||
code_example:
|
|
||||||
search_button: Search
|
|
||||||
search_examples: 'Search code examples:'
|
|
||||||
product_guides:
|
product_guides:
|
||||||
learning_paths_title: '{{ name }} learning paths'
|
learning_paths_title: '{{ name }} learning paths'
|
||||||
start_path: Start learning path
|
start_path: Start learning path
|
||||||
@@ -258,11 +243,6 @@ learning_track_nav:
|
|||||||
next_guide: Next
|
next_guide: Next
|
||||||
more_guides: More guides →
|
more_guides: More guides →
|
||||||
current_progress: '{i} of {n} in learning path'
|
current_progress: '{i} of {n} in learning path'
|
||||||
toggle_images:
|
|
||||||
off: Images are off, click to show
|
|
||||||
on: Images are on, click to hide
|
|
||||||
hide_single: Hide image
|
|
||||||
show_single: Show image
|
|
||||||
scroll_button:
|
scroll_button:
|
||||||
scroll_to_top: Scroll to top
|
scroll_to_top: Scroll to top
|
||||||
popovers:
|
popovers:
|
||||||
|
|||||||
Reference in New Issue
Block a user