chore(i18n,learn): processed translations (#45504)

This commit is contained in:
camperbot
2022-03-23 19:52:04 +05:30
committed by GitHub
parent dbb7f309a7
commit 3add6077ad
162 changed files with 2383 additions and 826 deletions

View File

@@ -16,7 +16,7 @@ dashedName: anonymous-message-board
- 使用 [我們的 Replit 啓動項目](https://replit.com/github/freeCodeCamp/boilerplate-project-messageboard)來完成你的項目。
- 使用一個你喜歡的站點生成器來完成項目。 需要確定包含了我們 GitHub 倉庫的所有文件。
完成本項目後,請將一個正常運行的 demo項目演示託管在可以公開訪問的平臺。 然後將 URL 提交到 `Solution Link` 中。 此外,還可以項目源碼提交到 `GitHub Link`
完成本項目後,請將一個正常運行的 demo項目演示託管在可以公開訪問的平臺。 然後將 URL 提交到 `Solution Link` 中。 此外,還可以提交一個指向項目源碼 `GitHub Link`
# --instructions--
@@ -116,49 +116,270 @@ async (getUserInput) => {
你可以向 `/api/replies/{board}` 發送一個 POST 請求,其中包括字段 `text``delete_password` & `thread_id`。 這將更新 `bumped_on` 日期到評論日期。 在主題的 `replies` 數組中,將保存一個對象,至少有 `_id``text``created_on``delete_password`& `reported` 這些屬性。
```js
async (getUserInput) => {
const url = getUserInput('url');
const body = await fetch(url + '/api/threads/fcc_test');
const thread = await body.json();
const date = new Date();
const text = `fcc_test_reply_${date}`;
const delete_password = 'delete_me';
const thread_id = thread[0]._id;
const replyCount = thread[0].replies.length;
const data = { text, delete_password, thread_id };
const res = await fetch(url + '/api/replies/fcc_test', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
if (res.ok) {
const checkData = await fetch(`${url}/api/replies/fcc_test?thread_id=${thread_id}`);
const parsed = await checkData.json();
try {
assert.equal(parsed.replies.length, replyCount + 1);
assert.equal(parsed.replies[0].text, text);
assert.equal(parsed._id, thread_id);
assert.equal(parsed.bumped_on, parsed.replies[0].created_on);
} catch (err) {
throw new Error(err.responseText || err.message);
}
} else {
throw new Error(`${res.status} ${res.statusText}`);
}
};
```
你可以向 `/api/threads/{board}` 發送一個 GET 請求。 返回的將是一個數組,包括論壇上最近的 10 個被回覆的主題,及每個主題最新的 3 個回帖。 `reported``delete_password` 字段將不會被髮送到客戶端。
```js
async (getUserInput) => {
const url = getUserInput('url');
const res = await fetch(url + '/api/threads/fcc_test');
if (res.ok) {
const threads = await res.json();
try {
assert.equal(res.status, 200);
assert.isAtMost(threads.length, 10);
for (let i = 0; i < threads.length; i++) {
assert.containsAllKeys(threads[i], ["_id", "text", "created_on", "bumped_on", "replies"]);
assert.isAtMost(threads[i].replies.length, 3);
assert.notExists(threads[i].delete_password);
assert.notExists(threads[i].reported);
for (let j = 0; j < threads[i].replies.length; j++) {
assert.notExists(threads[i].replies[j].delete_password);
assert.notExists(threads[i].replies[j].reported);
}
}
} catch (err) {
throw new Error(err.responseText || err.message);
}
} else {
throw new Error(`${res.status} ${res.statusText}`);
}
};
```
你可以向 `/api/replies/{board}?thread_id={thread_id}` 發送一個 GET 請求。 返回的將是帶有所有的回覆的整個主題,不包括與之前測試相同的客戶端字段。
```js
async (getUserInput) => {
const url = getUserInput('url');
let res = await fetch(url + '/api/threads/fcc_test');
const threads = await res.json();
const thread_id = threads[0]._id;
res = await fetch(`${url}/api/replies/fcc_test?thread_id=${thread_id}`);
if (res.ok) {
const thread = await res.json();
try {
assert.equal(res.status, 200);
assert.isObject(thread);
assert.containsAllKeys(thread, ["_id", "text", "created_on", "bumped_on", "replies"]);
assert.isArray(thread.replies);
assert.notExists(thread.delete_password);
assert.notExists(thread.reported);
for (let i = 0; i < thread.replies.length; i++) {
assert.notExists(thread.replies[i].delete_password);
assert.notExists(thread.replies[i].reported);
}
} catch (err) {
throw new Error(err.responseText || err.message);
}
} else {
throw new Error(`${res.status} ${res.statusText}`);
}
};
```
你可以向 `/api/threads/{board}` 發送一個 DELETE 請求,並傳遞 `thread_id` & `delete_password` 來刪除該線程。 返回的將是字符串 `incorrect password``success`
```js
async (getUserInput) => {
const url = getUserInput('url');
let res = await fetch(url + '/api/threads/fcc_test');
const threads = await res.json();
const thread_id = threads[0]._id;
let data = { thread_id, delete_password: "wrong_password" };
const res_invalid = await fetch(url + '/api/threads/fcc_test', {
method: 'DELETE',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
data = { thread_id, delete_password: "delete_me" };
res = await fetch(url + '/api/threads/fcc_test', {
method: 'DELETE',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
if (res.ok) {
const deleted = await res.text();
const not_deleted = await res_invalid.text();
try {
assert.equal(res.status, 200);
assert.equal(deleted, "success");
assert.equal(not_deleted, "incorrect password");
} catch (err) {
throw new Error(err.responseText || err.message);
}
} else {
throw new Error(`${res.status} ${res.statusText}`);
}
};
```
你可以向 `/api/replies/{board}` 發送一個 DELETE 請求,並傳遞 `thread_id``reply_id`& `delete_password`。 返回的將是字符串 `incorrect password``success`。 成功後,`reply_id` 的文本將更改爲 `[deleted]`
```js
async (getUserInput) => {
const url = getUserInput('url');
const thread_data = {
text: "fcc_test_thread",
delete_password: "delete_me",
};
await fetch(`${url}/api/threads/fcc_test`, {
method: "POST",
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(thread_data)
});
let res = await fetch(`${url}/api/threads/fcc_test`);
let threads = await res.json();
const thread_id = threads[0]._id;
const reply_data = { thread_id, text: "fcc_test_reply", delete_password: "delete_me" };
await fetch(`${url}/api/replies/fcc_test`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(reply_data)
});
res = await fetch(`${url}/api/threads/fcc_test`);
threads = await res.json();
const reply_id = threads[0].replies[0]._id;
const data = { thread_id, reply_id, delete_password: "delete_me" };
res = await fetch(url + '/api/replies/fcc_test', {
method: 'DELETE',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
if (res.ok) {
const deleted = await res.text();
try {
assert.equal(res.status, 200);
assert.equal(deleted, "success");
res = await fetch(`${url}/api/replies/fcc_test?thread_id=${thread_id}`);
const thread = await res.json();
assert.equal(thread._id, thread_id);
assert.equal(thread.replies[0]._id, reply_id);
assert.equal(thread.replies[0].text, "[deleted]");
} catch (err) {
throw new Error(err.responseText || err.message);
}
} else {
throw new Error(`${res.status} ${res.statusText}`);
}
};
```
你可以向 `/api/threads/{board}` 發送一個 PUT 請求,並傳遞 `thread_id`。 返回的將是字符串 `success``thread_id` 回覆的 `reported` 值將改爲 `true`
你可以向 `/api/threads/{board}` 發送一個 PUT 請求,並傳遞 `thread_id`。 返回的將是字符串 `reported``thread_id` 回覆的 `reported` 值將改爲 `true`
```js
async (getUserInput) => {
const url = getUserInput('url');
let res = await fetch(`${url}/api/threads/fcc_test`);
const threads = await res.json();
const report_id = threads[0]._id;
const data = { report_id };
res = await fetch(`${url}/api/threads/fcc_test`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
if (res.ok) {
const reported = await res.text();
try {
assert.equal(res.status, 200);
assert.equal(reported, "reported");
} catch (err) {
throw new Error(err.responseText || err.message);
}
} else {
throw new Error(`${res.status} ${res.statusText}`);
}
};
```
你可以通過向 `/api/replies/{board}` 發送 PUT 請求並傳遞 `thread_id` & `reply_id`。 返回的將是字符串 `success``reply_id``reported` 值將被改變爲 `true`
你可以通過向 `/api/replies/{board}` 發送 PUT 請求並傳遞 `thread_id` & `reply_id`。 返回的將是字符串 `reported``reply_id``reported` 值將被改變爲 `true`
```js
async (getUserInput) => {
const url = getUserInput('url');
let res = await fetch(`${url}/api/threads/fcc_test`);
const threads = await res.json();
const thread_id = threads[0]._id;
const reply_id = threads[0].replies[0]._id;
const data = { thread_id, reply_id };
res = await fetch(`${url}/api/replies/fcc_test`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
if (res.ok) {
const reported = await res.text();
try {
assert.equal(res.status, 200);
assert.equal(reported, "reported");
} catch (err) {
throw new Error(err.responseText || err.message);
}
} else {
throw new Error(`${res.status} ${res.statusText}`);
}
};
```
所有 10 項功能測試都已完成並通過。
```js
async (getUserInput) => {
const tests = await fetch(getUserInput('url') + '/_api/get-tests');
const parsed = await tests.json();
assert.isTrue(parsed.length >= 10);
parsed.forEach((test) => {
assert.equal(test.state, 'passed');
assert.isAtLeast(test.assertions.length, 1);
});
};
```
# --solutions--

View File

@@ -9,22 +9,74 @@ dashedName: port-scanner
# --description--
你將通過使用我們的 [Replit 入門代碼](https://replit.com/github/freeCodeCamp/boilerplate-port-scanner) 來完成本項目。
我們仍在開發 Python 課程的交互式教學部分。 目前,你可以在 YouTube 上通過 freeCodeCamp.org 上傳的一些視頻學習這個項目相關的知識。
- [Python for Everybody 視頻課程](https://www.freecodecamp.org/news/python-for-everybody/)14 小時)
- [Learn Python 視頻課程](https://www.freecodecamp.org/news/learn-python-video-course/)10 小時)
# --instructions--
使用 Python 創建一個端口掃描器。
你可以訪問 [Replit 上的完整項目描述和啓動代碼](https://replit.com/github/freeCodeCamp/boilerplate-port-scanner)
`port_scanner.py` 文件中,創建一個名爲 `get_open_ports` 的函數,它接受一個 `target` 參數和一個 `port_range` 參數。 `target` 可以是 URL 或 IP 地址。 `port_range` 是兩個數字的列表,表示要檢查的端口範圍的第一個和最後一個數字
在打開鏈接之後 fork 該項目。 根據 “README.md” 中的指示完成整個項目,然後在下面提交你的項目鏈接。
以下是如何調用該函數的示例:
Python 課程的交互式教學部分仍在開發當中。 目前freeCodeCamp YouTube 頻道上的一些視頻將會教授你這個項目要求的一些 Python 技能。
```py
get_open_ports("209.216.230.240", [440, 445])
get_open_ports("www.stackoverflow.com", [79, 82])
```
<ul>
<li>
<a href='https://www.freecodecamp.org/news/python-for-everybody/'>Python for Everybody 視頻課程</a>14 小時)
</li>
<li>
<a href='https://www.freecodecamp.org/news/learn-python-basics-in-depth-video-course/'>Learn Python 視頻課程</a>2 小時)
</li>
</ul>
該函數應返回給定範圍內的開放端口列表。
`get_open_ports` 函數還應採用可選的第三個參數 `True` 來表示“詳細”模式。 如果將其設置爲 true則該函數應返回描述性字符串而不是端口列表。
以下是詳細模式下應返回的字符串格式(`{}` 中的文本表示應顯示的信息):
```bash
Open ports for {URL} ({IP address})
PORT SERVICE
{port} {service name}
{port} {service name}
```
你可以使用 `common_ports.py` 中的字典爲每個端口獲取正確的服務名稱。
例如,如果函數是這樣調用的:
```py
port_scanner.get_open_ports("scanme.nmap.org", [20, 80], True)
```
它應該返回以下內容:
```bash
Open ports for scanme.nmap.org (45.33.32.156)
PORT SERVICE
22 ssh
80 http
```
確保包含正確的間距和換行符。
如果傳入 `get_open_ports` 函數的 URL 無效該函數應返回字符串“Error: Invalid hostname”。
如果傳入 `get_open_ports` 函數的 IP 地址無效該函數應返回字符串“Error: Invalid IP address”。
## 開發
`port_scanner.py` 中編寫你的代碼。 對於開發,你可以使用 `main.py` 來測試你的代碼。 單擊“運行”按鈕,`main.py` 將運行。
## 測試
這個項目的單元測試在 `test_module.py` 中。 爲了你的方便,我們將測試從 `test_module.py` 導入到 `main.py`。 只要你點擊“運行”按鈕,測試就會自動運行。
## 提交
複製項目的 URL 並將其提交給 freeCodeCamp。
# --hints--

View File

@@ -9,22 +9,51 @@ dashedName: sha-1-password-cracker
# --description--
你將通過使用我們的 [Replit 入門代碼](https://replit.com/github/freeCodeCamp/boilerplate-SHA-1-password-cracker) 來完成本項目。
我們仍在開發 Python 課程的交互式教學部分。 目前,你可以在 YouTube 上通過 freeCodeCamp.org 上傳的一些視頻學習這個項目相關的知識。
- [Python for Everybody 視頻課程](https://www.freecodecamp.org/news/python-for-everybody/)14 小時)
- [Learn Python 視頻課程](https://www.freecodecamp.org/news/learn-python-video-course/)10 小時)
# --instructions--
密碼不應以純文本形式存儲。 它們應該存儲爲哈希值,以防萬一密碼列表被泄露。 然而,並不是所有的哈希都是一樣的。
在這個項目中,你將通過創建一個密碼破解器來找出使用 SHA-1 散列的密碼,從而瞭解到良好安全的重要性。
你可以訪問 [Replit 上的完整項目描述和啓動代碼](https://replit.com/github/freeCodeCamp/boilerplate-SHA-1-password-cracker)
創建一個函數,該函數接受密碼的 SHA-1 哈希值,如果它是使用的前 10,000 個密碼之一,則返回該密碼。 如果 SHA-1 哈希不是數據庫中的密碼,則返回“密碼不在數據庫中”
進入該鏈接後fork 該項目。 一旦你根據 “README.md” 中的說明完成了項目,請在下面提交你的項目鏈接
該函數應該對 `top-10000-passwords.txt` 中的每個密碼進行散列,並將其與傳遞給函數的散列進行比較
我們仍在開發 Python 課程的交互式教學部分。 目前freeCodeCamp.org YouTube 頻道上的一些視頻可以教你這個項目所需的一些 Python 技能
該函數應採用名爲 `use_salts` 的可選第二個參數。 如果設置爲 true則文件 `known-salts.txt` 中的每個 salt 字符串,都應該在散列之前,和將它與傳遞給函數的哈希值進行比較之前,添加到 `top-10000-passwords.txt` 中的每個密碼的之前和之後
<ul>
<li>
<a href='https://www.freecodecamp.org/news/python-for-everybody/'>Python for Everybody 視頻課程</a>14 小時)
</li>
<li>
<a href='https://www.freecodecamp.org/news/learn-python-basics-in-depth-video-course/'>Learn Python 視頻課程</a>2 小時)
</li>
</ul>
以下是一些用於測試該功能的散列密碼:
- `b305921a3723cd5d70a375cd21a61e60aabb84ec` 應該返回 “sammy123”
- `c7ab388a5ebefbf4d550652f1eb4d833e5316e3e` 應該返回 “abacab”
- `5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8` 應該返回 “password”
以下是一些散列密碼,用於在 `use_salts` 設置爲 `True` 時測試該功能:
- `53d8b3dc9d39f0184144674e310185e41a87ffd5` 應該返回 “superman”
- `da5a4e8cf89539e66097acd2f8af128acae2f8ae` 應該返回 “q1w2e3r4t5”
- `ea3f62d498e3b98557f9f9cd0d905028b3b019e1` 應該返回 “bubbles1”
`hashlib` 庫已經爲你導入。 你應該在你的代碼中使用它。 [在此瞭解更多關於 “hashlib” 的信息](https://docs.python.org/3/library/hashlib.html)
## 開發
`password_cracker.py` 中編寫你的代碼。 對於開發,你可以使用 `main.py` 來測試你的代碼。 單擊“運行”按鈕,`main.py` 將運行。
## 測試
此項目的單元測試在 `test_module.py` 中。 爲了你的方便,我們將測試從 `test_module.py` 導入到 `main.py`。 只要你點擊“運行”按鈕,測試就會自動運行。
## 提交
複製項目的 URL 並將其提交給 freeCodeCamp。
# --hints--