@@ -5,7 +5,7 @@
|
||||
# --------------------------------------------------------------------------------
|
||||
# To update the sha, run `docker pull node:$VERSION-alpine`
|
||||
# look for something like: `Digest: sha256:0123456789abcdef`
|
||||
FROM node:20-alpine@sha256:7a91aa397f2e2dfbfcdad2e2d72599f374e0b0172be1d86eeb73f1d33f36a4b2 as base
|
||||
FROM node:20-alpine@sha256:291e84d956f1aff38454bbd3da38941461ad569a185c20aa289f71f37ea08e23 as base
|
||||
|
||||
# This directory is owned by the node user
|
||||
ARG APP_HOME=/home/node/app
|
||||
|
||||
@@ -73,14 +73,14 @@ Use `git status` to list all new or modified files that haven't yet been committ
|
||||
|
||||
To format code or text into its own distinct block, use triple backticks.
|
||||
|
||||
<pre>
|
||||
````text
|
||||
Some basic Git commands are:
|
||||
```
|
||||
git status
|
||||
git add
|
||||
git commit
|
||||
```
|
||||
</pre>
|
||||
````
|
||||
|
||||

|
||||
|
||||
@@ -250,8 +250,6 @@ You can create multiple levels of nested lists using the same method. For exampl
|
||||
|
||||
For more examples, see the [GitHub Flavored Markdown Spec](https://github.github.com/gfm/#example-265).
|
||||
|
||||
{% ifversion task-lists-v1 %}
|
||||
|
||||
## Task lists
|
||||
|
||||
{% data reusables.repositories.task-list-markdown %}
|
||||
@@ -261,7 +259,6 @@ If a task list item description begins with a parenthesis, you'll need to escape
|
||||
`- [ ] \(Optional) Open a followup issue`
|
||||
|
||||
For more information, see "[AUTOTITLE](/get-started/writing-on-github/working-with-advanced-formatting/about-task-lists)."
|
||||
{% endif %}
|
||||
|
||||
## Mentioning people and teams
|
||||
|
||||
|
||||
@@ -8,7 +8,9 @@ redirect_from:
|
||||
- /issues/tracking-your-work-with-issues/creating-issues/about-task-lists
|
||||
- /issues/tracking-your-work-with-issues/about-task-lists
|
||||
versions:
|
||||
feature: task-lists-v1
|
||||
fpt: '*'
|
||||
ghes: '*'
|
||||
ghec: '*'
|
||||
topics:
|
||||
- Pull requests
|
||||
- Issues
|
||||
|
||||
@@ -19,7 +19,7 @@ You can use {% data variables.product.prodname_projects_v2 %} to manage your wor
|
||||
|
||||
Breaking a large issue into smaller issues makes the work more manageable and enables team members to work in parallel. It also leads to smaller pull requests, which are easier to review.
|
||||
|
||||
To track how smaller issues fit into the larger goal, use {% ifversion task-lists-v1 %}task lists, milestones, or labels.{% else %} milestones or labels.{% endif %} For more information, see {% ifversion projects-v2-tasklists %}"[AUTOTITLE](/issues/tracking-your-work-with-issues/about-tasklists)"{% endif %}{% ifversion ghes %}"[AUTOTITLE](/get-started/writing-on-github/working-with-advanced-formatting/about-task-lists)"{% endif %}, "[AUTOTITLE](/issues/using-labels-and-milestones-to-track-work/about-milestones)", and "[AUTOTITLE](/issues/using-labels-and-milestones-to-track-work/managing-labels)."
|
||||
To track how smaller issues fit into the larger goal, use task lists, milestones, or labels. For more information, see {% ifversion projects-v2-tasklists %}"[AUTOTITLE](/issues/tracking-your-work-with-issues/about-tasklists)"{% endif %}{% ifversion ghes %}"[AUTOTITLE](/get-started/writing-on-github/working-with-advanced-formatting/about-task-lists)"{% endif %}, "[AUTOTITLE](/issues/using-labels-and-milestones-to-track-work/about-milestones)", and "[AUTOTITLE](/issues/using-labels-and-milestones-to-track-work/managing-labels)."
|
||||
|
||||
## Communicate
|
||||
|
||||
|
||||
@@ -74,8 +74,6 @@ Here is an example of an issue created for a large initiative, front-end work, i
|
||||
|
||||

|
||||
|
||||
{% ifversion task-lists-v1 %}
|
||||
|
||||
### Task list example
|
||||
|
||||
You can use task lists to break larger issues down into smaller tasks and to track issues as part of a larger goal. {% ifversion fpt or ghec %} Task lists have additional functionality when added to the body of an issue. You can see the number of tasks completed out of the total at the top of the issue, and if someone closes an issue linked in the task list, the checkbox will automatically be marked as complete.{% endif %} For more information, see "[AUTOTITLE](/get-started/writing-on-github/working-with-advanced-formatting/about-task-lists)."
|
||||
@@ -83,7 +81,6 @@ You can use task lists to break larger issues down into smaller tasks and to tra
|
||||
Below we have added a task list to our Project Octocat issue, breaking it down into smaller issues.
|
||||
|
||||

|
||||
{% endif %}
|
||||
|
||||
## Making decisions as a team
|
||||
|
||||
@@ -147,8 +144,8 @@ You have now learned about the tools {% data variables.product.prodname_dotcom %
|
||||
- "[AUTOTITLE](/repositories/creating-and-managing-repositories/about-repositories)" for learning more about creating repositories
|
||||
- "[AUTOTITLE](/issues/tracking-your-work-with-issues)" for learning more about different ways to create and manage issues
|
||||
- "[AUTOTITLE](/communities/using-templates-to-encourage-useful-issues-and-pull-requests/about-issue-and-pull-request-templates)" for learning more about issue templates
|
||||
- "[AUTOTITLE](/issues/using-labels-and-milestones-to-track-work/managing-labels)" for learning how to create, edit and delete labels{% ifversion task-lists-v1 %}
|
||||
- "[AUTOTITLE](/get-started/writing-on-github/working-with-advanced-formatting/about-task-lists)" for learning more about task lists{% endif %}
|
||||
- "[AUTOTITLE](/issues/using-labels-and-milestones-to-track-work/managing-labels)" for learning how to create, edit and delete labels
|
||||
- "[AUTOTITLE](/get-started/writing-on-github/working-with-advanced-formatting/about-task-lists)" for learning more about task lists
|
||||
{% ifversion projects-v2 %} - "[AUTOTITLE](/issues/planning-and-tracking-with-projects/learning-about-projects/about-projects)" for learning more about projects
|
||||
- "[AUTOTITLE](/issues/planning-and-tracking-with-projects/customizing-views-in-your-project/changing-the-layout-of-a-view)" for learning how to customize views for projects{% endif %}
|
||||
{% ifversion projects-v1 %}- "[AUTOTITLE](/issues/organizing-your-work-with-project-boards/managing-project-boards/about-project-boards)" for learning how to manage {% data variables.projects.projects_v1_boards %}{% endif %}
|
||||
|
||||
@@ -39,14 +39,11 @@ You can use markdown to add formatting, links, emojis, and more. For more inform
|
||||
|
||||

|
||||
|
||||
{% ifversion task-lists-v1 %}
|
||||
|
||||
## Adding a task list
|
||||
|
||||
It can be helpful to break large issues into smaller tasks, or to track multiple related issues in a single larger issue. Add a task list to your issue by prefacing list items with `[ ]`. Reference existing issues by issue number or URL. You can use plain text to track tasks that don't have a corresponding issue and convert them to issues later. For more information, see "[AUTOTITLE](/get-started/writing-on-github/working-with-advanced-formatting/about-task-lists)."
|
||||
|
||||

|
||||
{% endif %}
|
||||
|
||||
## Adding labels
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ If you are a repository maintainer, take these steps to manage and standardize t
|
||||
|
||||
Pull request templates let you customize and standardize the information you'd like to be included when someone creates a pull request in your repository. When you add a pull request template to your repository, project contributors will automatically see the template's contents in the pull request body. For more information, see "[AUTOTITLE](/communities/using-templates-to-encourage-useful-issues-and-pull-requests/creating-a-pull-request-template-for-your-repository)."
|
||||
|
||||
{% ifversion task-lists-v1 %} You can use pull request templates to standardize the review process for your repository. For example, you can include a list of tasks that you would like authors to complete before merging their pull requests, by adding a task list to the template. For more information, see "[AUTOTITLE](/get-started/writing-on-github/working-with-advanced-formatting/about-task-lists)."{% endif %}
|
||||
You can use pull request templates to standardize the review process for your repository. For example, you can include a list of tasks that you would like authors to complete before merging their pull requests, by adding a task list to the template. For more information, see "[AUTOTITLE](/get-started/writing-on-github/working-with-advanced-formatting/about-task-lists)."
|
||||
|
||||
You can request that contributors include an issue reference in their pull request body, so that merging the pull request will automatically close the issue. For more information, see "[AUTOTITLE](/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue)."
|
||||
|
||||
|
||||
7
package-lock.json
generated
7
package-lock.json
generated
@@ -104,6 +104,7 @@
|
||||
"@graphql-tools/load": "^8.0.0",
|
||||
"@octokit/rest": "^20.1.0",
|
||||
"@playwright/test": "1.44.0",
|
||||
"@types/accept-language-parser": "1.5.6",
|
||||
"@types/connect-datadog": "0.0.10",
|
||||
"@types/connect-timeout": "0.0.39",
|
||||
"@types/cookie": "0.6.0",
|
||||
@@ -3117,6 +3118,12 @@
|
||||
"version": "0.3.0",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/accept-language-parser": {
|
||||
"version": "1.5.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/accept-language-parser/-/accept-language-parser-1.5.6.tgz",
|
||||
"integrity": "sha512-lhSQUsAhAtbKjYgaw3f0c4EQKNQHFXhX87+OXUIqDHMkycvHGaqGskSRtnzysIUiqHPqNJ4BqI5SE++drsxx6A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/body-parser": {
|
||||
"version": "1.19.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
|
||||
|
||||
@@ -290,6 +290,7 @@
|
||||
"@graphql-tools/load": "^8.0.0",
|
||||
"@octokit/rest": "^20.1.0",
|
||||
"@playwright/test": "1.44.0",
|
||||
"@types/accept-language-parser": "1.5.6",
|
||||
"@types/connect-datadog": "0.0.10",
|
||||
"@types/connect-timeout": "0.0.39",
|
||||
"@types/cookie": "0.6.0",
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
} from './set-fastly-surrogate-key.js'
|
||||
import handleErrors from '@/observability/middleware/handle-errors'
|
||||
import handleNextDataPath from './handle-next-data-path'
|
||||
import detectLanguage from '@/languages/middleware/detect-language.js'
|
||||
import detectLanguage from '@/languages/middleware/detect-language'
|
||||
import reloadTree from './reload-tree.js'
|
||||
import context from './context/context.js'
|
||||
import shortVersions from '@/versions/middleware/short-versions.js'
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import languages, { languageKeys } from '#src/languages/lib/languages.js'
|
||||
import type { Request, Response, NextFunction } from 'express'
|
||||
import parser from 'accept-language-parser'
|
||||
import type { Language as parserLanguage } from 'accept-language-parser'
|
||||
|
||||
import { USER_LANGUAGE_COOKIE_NAME } from '#src/frame/lib/constants.js'
|
||||
import languages, { languageKeys } from '@/languages/lib/languages.js'
|
||||
import { USER_LANGUAGE_COOKIE_NAME } from '@/frame/lib/constants.js'
|
||||
import type { ExtendedRequest, Languages } from '@/types'
|
||||
|
||||
const chineseRegions = [
|
||||
'CN', // Mainland
|
||||
@@ -10,25 +13,28 @@ const chineseRegions = [
|
||||
'TW', // Taiwan
|
||||
]
|
||||
|
||||
function translationExists(language) {
|
||||
function translationExists(language: parserLanguage) {
|
||||
if (language.code === 'zh') {
|
||||
return chineseRegions.includes(language.region)
|
||||
return language.region && chineseRegions.includes(language.region)
|
||||
}
|
||||
// 92BD1212-61B8-4E7A: Remove ` && !languages[language.code].wip` for the public ship of ko, fr, de, ru
|
||||
return languageKeys.includes(language.code) && !languages[language.code].wip
|
||||
return languageKeys.includes(language.code) && !(languages as Languages)[language.code].wip
|
||||
}
|
||||
|
||||
function getLanguageCode(language) {
|
||||
return language.code === 'cn' && chineseRegions.includes(language.region) ? 'zh' : language.code
|
||||
function getLanguageCode(language: parserLanguage) {
|
||||
return language.code === 'cn' && language.region && chineseRegions.includes(language.region)
|
||||
? 'zh'
|
||||
: language.code
|
||||
}
|
||||
|
||||
function getUserLanguage(browserLanguages) {
|
||||
function getUserLanguage(browserLanguages: parserLanguage[]) {
|
||||
try {
|
||||
let numTopPreferences = 1
|
||||
for (let lang = 0; lang < browserLanguages.length; lang++) {
|
||||
// If language has multiple regions, Chrome adds the non-region language to list
|
||||
if (lang > 0 && browserLanguages[lang].code !== browserLanguages[lang - 1].code)
|
||||
if (lang > 0 && browserLanguages[lang].code !== browserLanguages[lang - 1].code) {
|
||||
numTopPreferences++
|
||||
}
|
||||
if (translationExists(browserLanguages[lang]) && numTopPreferences < 3) {
|
||||
return getLanguageCode(browserLanguages[lang])
|
||||
}
|
||||
@@ -38,26 +44,27 @@ function getUserLanguage(browserLanguages) {
|
||||
}
|
||||
}
|
||||
|
||||
function getUserLanguageFromCookie(req) {
|
||||
const value = req.cookies[USER_LANGUAGE_COOKIE_NAME]
|
||||
function getUserLanguageFromCookie(req: Request) {
|
||||
const value: undefined | string = req.cookies[USER_LANGUAGE_COOKIE_NAME]
|
||||
|
||||
// 92BD1212-61B8-4E7A: Remove ` && !languages[value].wip` for the public ship of ko, fr, de, ru
|
||||
if (value && languages[value] && !languages[value].wip) {
|
||||
if (value && (languages as Languages)[value] && !(languages as Languages)[value].wip) {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
// determine language code from a path. Default to en if no valid match
|
||||
export function getLanguageCodeFromPath(path) {
|
||||
export function getLanguageCodeFromPath(path: string) {
|
||||
const maybeLanguage = (path.split('/')[path.startsWith('/_next/data/') ? 4 : 1] || '').slice(0, 2)
|
||||
return languageKeys.includes(maybeLanguage) ? maybeLanguage : 'en'
|
||||
}
|
||||
|
||||
export function getLanguageCodeFromHeader(req) {
|
||||
export function getLanguageCodeFromHeader(req: Request) {
|
||||
const browserLanguages = parser.parse(req.headers['accept-language'])
|
||||
return getUserLanguage(browserLanguages)
|
||||
}
|
||||
|
||||
export default function detectLanguage(req, res, next) {
|
||||
export default function detectLanguage(req: ExtendedRequest, res: Response, next: NextFunction) {
|
||||
req.language = getLanguageCodeFromPath(req.path)
|
||||
// Detecting browser language by user preference
|
||||
req.userLanguage = getUserLanguageFromCookie(req)
|
||||
14
src/types.ts
14
src/types.ts
@@ -10,5 +10,19 @@ export type ExtendedRequest = Request & {
|
||||
currentCategory?: string
|
||||
error?: Error
|
||||
}
|
||||
language?: string
|
||||
userLanguage?: string
|
||||
// Add more properties here as needed
|
||||
}
|
||||
|
||||
type Language = {
|
||||
name: string
|
||||
code: string
|
||||
hreflang: string
|
||||
dir: string
|
||||
wip: boolean
|
||||
}
|
||||
|
||||
export type Languages = {
|
||||
[key: string]: Language
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user