Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf507b78

Browse files
authored
Merge pull requestalexmojaki#288 from alexmojaki/frontend-translations
Frontend translations
2 parents70353cc +1a939c8 commitf507b78

File tree

17 files changed

+458
-157
lines changed

17 files changed

+458
-157
lines changed

‎core/generate_static_files.py‎

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,22 @@
2525
frompathlibimportPath
2626

2727
importbirdseye
28-
fromlittleutilsimportstrip_required_prefix,json_to_file
28+
fromlittleutilsimportstrip_required_prefix,json_to_file,file_to_json
29+
frommarkdownimportmarkdown
2930

3031
fromcoreimporttranslationast
3132
fromcore.checkerimportcheck_entry
3233
fromcore.runner.utilsimportsite_packages
3334
fromcore.textimportget_pages,step_test_entries,load_chapters
35+
fromcore.utilsimportunwrapped_markdown,new_tab_links
3436

3537
str("import sentry_sdk after core.utils for stubs")
3638
importsentry_sdk# noqa imported lazily
3739

40+
this_dir=Path(__file__).parent
41+
frontend=this_dir/"../frontend"
42+
frontend_src=frontend/"src"
43+
3844

3945
defrun_steps():
4046
for*_,entryinstep_test_entries():
@@ -78,16 +84,29 @@ def tarfile_filter(tar_info):
7884
returntar_info
7985

8086

87+
deffrontend_terms():
88+
forkey,valueinfile_to_json(frontend_src/"english_terms.json").items():
89+
translation=t.get(f"frontend.{key}",value)
90+
91+
if"\n"intranslation:
92+
value=markdown(translation)
93+
else:
94+
value=unwrapped_markdown(translation)
95+
96+
result=new_tab_links(value)
97+
ifvalue!=result:
98+
assertkey.startswith("question_wizard_")
99+
100+
yieldkey,result
101+
102+
81103
defmain():
82104
print("Generating files...")
83105
t.set_language(os.environ.get("FUTURECODER_LANGUAGE","en"))
84-
this_dir=Path(__file__).parent
85-
frontend=this_dir/"../frontend"
86-
frontend_src=frontend/"src"
87106

88-
chapters=list(load_chapters())
107+
json_to_file(list(load_chapters()),frontend_src/"chapters.json")
89108
json_to_file(get_pages(),frontend_src/"book/pages.json.load_by_url")
90-
json_to_file(chapters,frontend_src/"chapters.json")
109+
json_to_file(dict(frontend_terms()),frontend_src/"terms.json",indent=4)
91110

92111
birdseye_dest=frontend/"public/birdseye"
93112
shutil.rmtree(birdseye_dest,ignore_errors=True)

‎core/markdown_extensions.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def run(self, root):
4343
ifcopyable:
4444
node.append(
4545
etree.fromstring(
46-
f'<button>{t.Terms.copy_button}</button>'
46+
f'<buttonx x-first x-last"> copy-button">{t.Terms.copy_button}</button>'
4747
)
4848
)
4949
node.set("class",node.get("class","")+" copyable")

‎core/question_wizard.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
fromlittleutilsimportonly
77

88
fromcore.lintingimportlint
9-
fromcore.utilsimporthighlighted_markdown
9+
fromcore.utilsimporthighlighted_markdown,new_tab_links
1010

1111

1212
definput_messages(input_nodes):
@@ -82,5 +82,5 @@ def question_wizard_check(entry, output, runner):
8282
else:
8383
messages.append(t.Terms.q_wiz_debugger)
8484

85-
messages= [highlighted_markdown(message)formessageinmessages]
85+
messages= [new_tab_links(highlighted_markdown(message))formessageinmessages]
8686
returnmessages

‎core/utils.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,10 @@ def markdown_codes(text):
164164
returnhighlighted_markdown_and_codes(text)[1]
165165

166166

167+
defnew_tab_links(s):
168+
returns.replace("<a href=",'<a target="_blank" rel="noreferrer" href=')
169+
170+
167171
defshuffled(it):
168172
result=list(it)
169173
shuffle(result)

‎frontend/src/App.js‎

Lines changed: 31 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import {interrupt, runCode, terminalRef} from "./RunCode";
4545
importfirebasefrom"firebase/app";
4646
import{TableOfContents}from"./TableOfContents";
4747
importHeaderLoginInfofrom"./components/HeaderLoginInfo";
48+
import*astermsfrom"./terms.json"
4849

4950

5051
constEditorButtons=(
@@ -64,15 +65,15 @@ const EditorButtons = (
6465
className="btn btn-danger"
6566
onClick={()=>interrupt()}
6667
>
67-
<FontAwesomeIconicon={faStop}/>Stop
68+
<FontAwesomeIconicon={faStop}/>{terms.stop}
6869
</button>
6970
:
7071
<button
7172
disabled={disabled}
7273
className="btn btn-primary"
7374
onClick={()=>runCode({source:"editor"})}
7475
>
75-
<FontAwesomeIconicon={faPlay}/>Run
76+
<FontAwesomeIconicon={faPlay}/>{terms.run}
7677
</button>
7778
}
7879

@@ -144,7 +145,7 @@ const EditorButtons = (
144145
{showQuestionButton&&!disabled&&
145146
<aclassName="btn btn-success"
146147
href={"#question"}>
147-
<FontAwesomeIconicon={faQuestionCircle}/>Ask for help
148+
<FontAwesomeIconicon={faQuestionCircle}/>{terms.ask_for_help}
148149
</a>}
149150
</div>;
150151

@@ -200,42 +201,11 @@ const QuestionWizard = (
200201
expectedOutput,
201202
})=>
202203
<>
203-
<h1>Question Wizard</h1>
204-
<p>
205-
If you need help, there are many sites like
206-
{" "}<atarget="_blank"rel="noreferrer"href="https://stackoverflow.com/">Stack Overflow</a>{" "}
207-
and<atarget="_blank"rel="noreferrer"href="https://www.reddit.com/r/learnpython/">reddit</a> where
208-
you can ask questions.
209-
This is a tool to help you write a good quality question that is likely to get answers.
210-
</p>
211-
<p>
212-
Enter and run your code on the right. If you don't have any code because you don't know where to get started,
213-
I'm afraid this tool can't help you. You can still ask for help, but it might be good to first
214-
read<atarget="_blank"rel="noreferrer"
215-
href="https://stackoverflow.com/help/dont-ask">What types of questions should I avoid asking?</a>
216-
</p>
217-
<p>
218-
If your question is about servers (e.g. Django or Flask), web requests, databases, or a package that can't be
219-
imported here, then this tool won't work. However, just because your current code<em>involves</em> those things,
220-
that doesn't mean that's what your question is<em>about</em>. If you're having a general
221-
Python/programming/logic problem, then extract that problem from the other stuff.
222-
Python with Django is still Python. If you can't do that, then
223-
read<atarget="_blank"rel="noreferrer"
224-
href="https://stackoverflow.com/help/minimal-reproducible-example">
225-
How to create a Minimal, Reproducible Example</a> before
226-
asking your question.
227-
</p>
204+
<h1>{terms.question_wizard}</h1>
205+
<divdangerouslySetInnerHTML={{__html:terms.question_wizard_intro}}/>
228206
<hr/>
229207
{requestExpectedOutput&&<>
230-
<p>
231-
Good, now enter the output you expect/want from your program below.
232-
What would it show if it worked correctly?
233-
If it's not supposed to output anything, then add some<code>print()</code> calls to your
234-
code so that it would output something useful.
235-
</p>
236-
<p>
237-
When you're done, click 'Run' again to generate your question.
238-
</p>
208+
<divdangerouslySetInnerHTML={{__html:terms.question_wizard_expected_output}}/>
239209
<AceEditor
240210
onChange={value=>bookSetState("questionWizard.expectedOutput",value)}
241211
theme={"monokai"}
@@ -273,10 +243,10 @@ const Markdown = (
273243
onClick={(event)=>{
274244
// https://stackoverflow.com/questions/54109790/how-to-add-onclick-event-to-a-string-rendered-by-dangerouslysetinnerhtml-in-reac
275245
constbutton=event.target.closest("button");
276-
if(button&&event.currentTarget.contains(button)&&button.textContent==="Copy"){
246+
if(button&&event.currentTarget.contains(button)&&button.classList.contains("copy-button")){
277247
constcodeElement=button.closest("code");
278248
letcodeText=codeElement.textContent;
279-
codeText=codeText.substring(0,codeText.length-"\nCopy".length);
249+
codeText=codeText.substring(0,codeText.length-1-button.textContent.length);
280250
copyFunc(codeText);
281251
}
282252
}}
@@ -309,13 +279,13 @@ const CourseText = (
309279
{page.index>0&&
310280
<buttonclassName="btn btn-primary previous-button"
311281
onClick={()=>movePage(-1)}>
312-
Previous
282+
{terms.previous}
313283
</button>}
314284
{" "}
315285
{page.index<Object.keys(pages).length-1&&step_index===page.steps.length-1&&
316286
<buttonclassName="btn btn-success next-button"
317287
onClick={()=>movePage(+1)}>
318-
Next
288+
{terms.next}
319289
</button>}
320290
</div>
321291
<br/>
@@ -377,7 +347,7 @@ class AppComponent extends React.Component {
377347
<HeaderLoginInfoemail={user.email}/>
378348
</span>
379349
<aclassName="nav-item nav-link"href="#toc">
380-
<FontAwesomeIconicon={faListOl}/>Table of Contents
350+
<FontAwesomeIconicon={faListOl}/>{terms.table_of_contents}
381351
</a>
382352
</nav>
383353

@@ -448,9 +418,9 @@ const StepButton = ({delta, label}) =>
448418

449419
constStepButtons=()=>
450420
<divstyle={{position:"fixed",bottom:0}}>
451-
<StepButtondelta={-1}label="Reverse step"/>
421+
<StepButtondelta={-1}label={terms.reverse_step}/>
452422
{" "}
453-
<StepButtondelta={+1}label="Skip step"/>
423+
<StepButtondelta={+1}label={terms.skip_step}/>
454424
</div>
455425

456426

@@ -462,21 +432,22 @@ const MenuPopup = ({user}) =>
462432
</button>}
463433
>
464434
{close=><divclassName="menu-popup">
465-
<p><button
466-
className="btn btn-danger"
467-
onClick={()=>{
468-
close();
469-
bookSetState("user.uid",null)
470-
firebase.auth().signOut();
471-
}}
472-
>
473-
<FontAwesomeIconicon={faSignOutAlt}/> Sign out
474-
</button></p>
435+
<p>
436+
<button
437+
className="btn btn-danger"
438+
onClick={()=>{
439+
close();
440+
bookSetState("user.uid",null)
441+
firebase.auth().signOut();
442+
}}
443+
>
444+
<FontAwesomeIconicon={faSignOutAlt}/>{terms.sign_out}
445+
</button></p>
475446
<p>
476447
<Popup
477448
trigger={
478449
<buttonclassName="btn btn-primary">
479-
<FontAwesomeIconicon={faCog}/>Settings
450+
<FontAwesomeIconicon={faCog}/>{terms.settings}
480451
</button>
481452
}
482453
modal
@@ -489,7 +460,7 @@ const MenuPopup = ({user}) =>
489460
<Popup
490461
trigger={
491462
<buttonclassName="btn btn-success">
492-
<FontAwesomeIconicon={faBug}/>Feedback
463+
<FontAwesomeIconicon={faBug}/>{terms.feedback}
493464
</button>
494465
}
495466
modal
@@ -505,17 +476,17 @@ const MenuPopup = ({user}) =>
505476

506477
constSettingsModal=({user})=>(
507478
<divclassName="settings-modal">
508-
<h1>Settings</h1>
479+
<h1>{terms.settings}</h1>
509480
<br/>
510481
<label>
511482
<Toggle
512483
defaultChecked={user.developerMode}
513484
onChange={(e)=>setDeveloperMode(e.target.checked)}
514485
/>
515-
<b>Developer mode</b>
486+
<b>{terms.developer_mode}</b>
516487
</label>
517488

518-
<p>Enables the "Reverse step" and "Skip step" buttons.</p>
489+
<p>{terms.developer_mode_description}</p>
519490
</div>
520491
)
521492

@@ -531,22 +502,7 @@ const checkCopy = () => {
531502
])
532503
.some((node)=>node&&!node.classList.contains("copyable"))
533504
){
534-
addMessage(`
535-
<div>
536-
<p><strong>STOP!</strong></p>
537-
<p>
538-
Try to avoid copy pasting code. You will learn, absorb, and remember better if you
539-
type in the code yourself.
540-
</p>
541-
<p>
542-
When copying is appropriate, there will be a button to click to make it easy.
543-
If there's no button, try typing.
544-
</p>
545-
<p>
546-
Having said that, we're not going to force you. Copy if you really want to.
547-
</p>
548-
</div>
549-
`);
505+
addMessage(terms.copy_warning);
550506
}
551507
}
552508

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp