Skip to content

Commit c46ca17

Browse files
committed
Merge branch 'master' of github.com:sagemathinc/cocalc
2 parents 2769c18 + bfbe65d commit c46ca17

38 files changed

+718
-515
lines changed

src/packages/frontend/account/other-settings.tsx

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { FormattedMessage, useIntl } from "react-intl";
99

1010
import { Checkbox, Panel } from "@cocalc/frontend/antd-bootstrap";
1111
import { Rendered, redux, useTypedRedux } from "@cocalc/frontend/app-framework";
12+
import { useLocalizationCtx } from "@cocalc/frontend/app/localize";
1213
import {
1314
A,
1415
HelpIcon,
@@ -22,7 +23,7 @@ import {
2223
import AIAvatar from "@cocalc/frontend/components/ai-avatar";
2324
import { IS_MOBILE, IS_TOUCH } from "@cocalc/frontend/feature";
2425
import LLMSelector from "@cocalc/frontend/frame-editors/llm/llm-selector";
25-
import { labels } from "@cocalc/frontend/i18n";
26+
import { LOCALIZATIONS, labels } from "@cocalc/frontend/i18n";
2627
import {
2728
VBAR_EXPLANATION,
2829
VBAR_KEY,
@@ -33,6 +34,7 @@ import { NewFilenameFamilies } from "@cocalc/frontend/project/utils";
3334
import track from "@cocalc/frontend/user-tracking";
3435
import { webapp_client } from "@cocalc/frontend/webapp-client";
3536
import { DEFAULT_NEW_FILENAMES, NEW_FILENAMES } from "@cocalc/util/db-schema";
37+
import { OTHER_SETTINGS_REPLY_ENGLISH_KEY } from "@cocalc/util/i18n/const";
3638
import { dark_mode_mins, get_dark_mode_config } from "./dark-mode";
3739
import { I18NSelector, I18N_MESSAGE, I18N_TITLE } from "./i18n-selector";
3840
import Tours from "./tours";
@@ -60,6 +62,7 @@ interface Props {
6062

6163
export function OtherSettings(props: Readonly<Props>): JSX.Element {
6264
const intl = useIntl();
65+
const { locale } = useLocalizationCtx();
6366
const isCoCalcCom = useTypedRedux("customize", "is_cocalc_com");
6467
const user_defined_llm = useTypedRedux("customize", "user_defined_llm");
6568

@@ -552,6 +555,24 @@ export function OtherSettings(props: Readonly<Props>): JSX.Element {
552555
);
553556
}
554557

558+
function render_llm_reply_language(): Rendered {
559+
return (
560+
<Checkbox
561+
checked={!!props.other_settings.get(OTHER_SETTINGS_REPLY_ENGLISH_KEY)}
562+
onChange={(e) => {
563+
on_change(OTHER_SETTINGS_REPLY_ENGLISH_KEY, e.target.checked);
564+
}}
565+
>
566+
<FormattedMessage
567+
id="account.other-settings.llm.reply_language"
568+
defaultMessage={`<strong>Always reply in English:</strong>
569+
If set, the replies are always in English. Otherwise, it replies in your language ({lang}).`}
570+
values={{ lang: intl.formatMessage(LOCALIZATIONS[locale].trans) }}
571+
/>
572+
</Checkbox>
573+
);
574+
}
575+
555576
function render_custom_llm(): Rendered {
556577
// on cocalc.com, do not even show that they're disabled
557578
if (isCoCalcCom && !user_defined_llm) return;
@@ -578,6 +599,7 @@ export function OtherSettings(props: Readonly<Props>): JSX.Element {
578599
>
579600
{render_disable_all_llm()}
580601
{render_language_model()}
602+
{render_llm_reply_language()}
581603
{render_custom_llm()}
582604
</Panel>
583605
);

src/packages/frontend/account/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
OTHER_SETTINGS_USERDEFINED_LLM,
1515
} from "@cocalc/util/db-schema/defaults";
1616
import { LanguageModel } from "@cocalc/util/db-schema/llm-utils";
17+
import { OTHER_SETTINGS_REPLY_ENGLISH_KEY } from "@cocalc/util/i18n/const";
1718
import { PassportStrategyFrontend } from "@cocalc/util/types/passport-types";
1819
import { SETTINGS_LANGUAGE_MODEL_KEY } from "./useLanguageModelSetting";
1920

@@ -50,6 +51,7 @@ export interface AccountState {
5051
news_read_until: number; // JavaScript timestamp in milliseconds
5152
[OTHER_SETTINGS_USERDEFINED_LLM]: string; // string is JSON: CustomLLM[]
5253
[OTHER_SETTINGS_LOCALE_KEY]?: string;
54+
[OTHER_SETTINGS_REPLY_ENGLISH_KEY]?: string;
5355
}>;
5456
stripe_customer?: TypedMap<{
5557
subscriptions: { data: Map<string, any> };

src/packages/frontend/client/llm.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ import {
2424
import * as message from "@cocalc/util/message";
2525
import type { WebappClient } from "./client";
2626
import type { History } from "./types";
27+
import {
28+
LOCALIZATIONS,
29+
OTHER_SETTINGS_LOCALE_KEY,
30+
OTHER_SETTINGS_REPLY_ENGLISH_KEY,
31+
} from "@cocalc/util/i18n/const";
32+
import { sanitizeLocale } from "@cocalc/frontend/i18n";
2733

2834
interface QueryLLMProps {
2935
input: string;
@@ -111,6 +117,19 @@ export class LLMClient {
111117
}
112118
}
113119

120+
// append a sentence to request to translate the output to the user's language – unless disabled
121+
const other_settings = redux.getStore("account").get("other_settings");
122+
const alwaysEnglish = !!other_settings.get(
123+
OTHER_SETTINGS_REPLY_ENGLISH_KEY,
124+
);
125+
const locale = sanitizeLocale(
126+
other_settings.get(OTHER_SETTINGS_LOCALE_KEY),
127+
);
128+
if (!alwaysEnglish && locale != "en") {
129+
const lang = LOCALIZATIONS[locale].name; // name is always in english
130+
system = `${system}\n\nYour answer must be written in the language ${lang}.`;
131+
}
132+
114133
const is_cocalc_com = redux.getStore("customize").get("is_cocalc_com");
115134

116135
if (!isFreeModel(model, is_cocalc_com)) {
Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,45 @@
11
import { CSS } from "@cocalc/frontend/app-framework";
22
import { useBottomScroller } from "@cocalc/frontend/app-framework/use-bottom-scroller";
3-
import { Paragraph } from "@cocalc/frontend/components";
43
import { COLORS } from "@cocalc/util/theme";
4+
import StaticMarkdown from "@cocalc/frontend/editors/slate/static-markdown";
5+
import { Paragraph } from "@cocalc/frontend/components";
6+
7+
const STYLE = {
8+
border: "1px solid lightgrey",
9+
borderRadius: "5px",
10+
margin: "5px 0",
11+
padding: "10px",
12+
overflowY: "auto",
13+
maxHeight: "150px",
14+
fontSize: "85%",
15+
fontFamily: "monospace",
16+
whiteSpace: "pre-wrap",
17+
color: COLORS.GRAY_M,
18+
} as const;
519

620
interface Props {
721
input: JSX.Element | string;
822
style?: CSS;
923
scrollBottom?: boolean;
1024
}
1125

12-
export function RawPrompt({ input, style, scrollBottom = false }: Props) {
26+
export function RawPrompt({
27+
input,
28+
style: style0,
29+
scrollBottom = false,
30+
}: Props) {
1331
const ref = useBottomScroller(scrollBottom, input);
14-
15-
return (
16-
<Paragraph
17-
ref={ref}
18-
style={{
19-
border: "1px solid lightgrey",
20-
borderRadius: "5px",
21-
margin: "5px 0",
22-
padding: "10px",
23-
overflowY: "auto",
24-
maxHeight: "150px",
25-
fontSize: "85%",
26-
fontFamily: "monospace",
27-
whiteSpace: "pre-wrap",
28-
color: COLORS.GRAY_M,
29-
...style,
30-
}}
31-
>
32-
{input}
33-
</Paragraph>
34-
);
32+
const style = { ...STYLE, ...style0 };
33+
if (typeof input == "string") {
34+
// this looks so much nicer; I realize it doesn't implement scrollBottom.
35+
// But just dropping the input as plain text like below just seems
36+
// utterly broken!
37+
return <StaticMarkdown style={style} value={input} />;
38+
} else {
39+
return (
40+
<Paragraph ref={ref} style={style}>
41+
{input}
42+
</Paragraph>
43+
);
44+
}
3545
}

src/packages/frontend/frame-editors/code-editor/actions.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1374,8 +1374,7 @@ export class Actions<
13741374
// to make typescript happy
13751375
return;
13761376
}
1377-
this.set_frame_tree({ id, font_size });
1378-
this.focus(id);
1377+
this.set_font_size(id, font_size);
13791378
}
13801379

13811380
increase_font_size(id: string): void {
@@ -1386,6 +1385,9 @@ export class Actions<
13861385
this.change_font_size(-1, id);
13871386
}
13881387

1388+
// ATTN: this is overloaded in some derived classes, eg. latex to adjust settings
1389+
// based on font size changing. Code should call this to set the font size instead
1390+
// of directly modifying frame tree.
13891391
set_font_size(id: string, font_size: number): void {
13901392
this.set_frame_tree({ id, font_size });
13911393
this.focus(id);

src/packages/frontend/frame-editors/latex-editor/actions.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1597,4 +1597,9 @@ export class Actions extends BaseActions<LatexEditorState> {
15971597
chatgptCodeDescription(): string {
15981598
return "Put any LaTeX you generate in the answer in a fenced code block with info string 'tex'.";
15991599
}
1600+
1601+
set_font_size(id: string, font_size: number): void {
1602+
super.set_font_size(id, font_size);
1603+
this.update_gutters_soon();
1604+
}
16001605
}

src/packages/frontend/frame-editors/latex-editor/editor.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import { CodemirrorEditor } from "../code-editor/codemirror-editor";
1414
import { createEditor } from "../frame-tree/editor";
1515
import { EditorDescription } from "../frame-tree/types";
1616
import { TableOfContents } from "../markdown-editor/table-of-contents";
17-
//import { SETTINGS_SPEC } from "../settings/editor";
1817
import { terminal } from "../terminal-editor/editor";
1918
import { time_travel } from "../time-travel-editor/editor";
2019
import { Build } from "./build";

src/packages/frontend/frame-editors/latex-editor/gutters.tsx

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,14 @@
99
// one gets a gutter mark, with pref to errors. The main error log shows everything, so this should be OK.
1010

1111
import { Popover } from "antd";
12-
1312
import { Icon } from "@cocalc/frontend/components";
14-
//import { Actions } from "@cocalc/frontend/frame-editors/code-editor/actions";
1513
import { Localize } from "@cocalc/frontend/app/localize";
1614
import HelpMeFix from "@cocalc/frontend/frame-editors/llm/help-me-fix";
1715
import { capitalize } from "@cocalc/util/misc";
18-
import { Actions } from "./actions";
16+
import type { Actions } from "./actions";
1917
import { SPEC, SpecItem } from "./errors-and-warnings";
2018
import { Error, IProcessedLatexLog } from "./latex-log-parser";
19+
import { useFrameContext } from "@cocalc/frontend/frame-editors/frame-tree/frame-context";
2120

2221
export function update_gutters(opts: {
2322
log: IProcessedLatexLog;
@@ -36,27 +35,36 @@ export function update_gutters(opts: {
3635
opts.set_gutter(
3736
item.file,
3837
item.line - 1,
39-
component(
40-
item.level,
41-
item.message,
42-
item.content,
43-
opts.actions,
44-
group,
45-
item.line,
46-
),
38+
<Component
39+
level={item.level}
40+
message={item.message}
41+
content={item.content}
42+
actions={opts.actions}
43+
group={group}
44+
line={item.line}
45+
/>,
4746
);
4847
}
4948
}
5049
}
5150

52-
function component(
53-
level: string,
54-
message: string,
55-
content: string | undefined,
56-
actions: Actions,
57-
group: string,
58-
line: number,
59-
) {
51+
function Component({
52+
level,
53+
message,
54+
content,
55+
actions,
56+
group,
57+
line,
58+
}: {
59+
level: string;
60+
message: string;
61+
content: string | undefined;
62+
actions: Actions;
63+
group: string;
64+
line: number;
65+
}) {
66+
const { desc } = useFrameContext();
67+
const fontSize = desc?.get("font_size");
6068
const spec: SpecItem = SPEC[level];
6169
if (content === undefined) {
6270
content = message;
@@ -69,10 +77,9 @@ function component(
6977
return (
7078
<Localize>
7179
<Popover
72-
title={message}
73-
content={
74-
<div>
75-
{content}
80+
title={
81+
<span style={{ fontSize }}>
82+
{message}{" "}
7683
{group == "errors" && (
7784
<>
7885
<br />
@@ -97,14 +104,26 @@ function component(
97104
/>
98105
</>
99106
)}
107+
</span>
108+
}
109+
content={
110+
<div
111+
style={{
112+
fontSize,
113+
maxWidth: "70vw",
114+
maxHeight: "70vh",
115+
overflow: "auto",
116+
}}
117+
>
118+
{content}
100119
</div>
101120
}
102121
placement={"right"}
103122
mouseEnterDelay={0}
104123
>
105124
<Icon
106125
name={spec.icon}
107-
style={{ color: spec.color, cursor: "pointer" }}
126+
style={{ color: spec.color, cursor: "pointer", fontSize }}
108127
/>
109128
</Popover>
110129
</Localize>

src/packages/frontend/frame-editors/llm/help-me-fix.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { Alert, Button, Space } from "antd";
77
import type { BaseButtonProps } from "antd/lib/button/button";
88
import { CSSProperties, useState } from "react";
99
import useAsyncEffect from "use-async-effect";
10-
1110
import { useLanguageModelSetting } from "@cocalc/frontend/account/useLanguageModelSetting";
1211
import getChatActions from "@cocalc/frontend/chat/get-actions";
1312
import { AIAvatar, RawPrompt } from "@cocalc/frontend/components";

src/packages/frontend/i18n/trans/ar_EG.json

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"account.other-settings.katex": "<strong>KaTeX:</strong> محاولة عرض الصيغ باستخدام {katex} (أسرع بكثير، ولكن بدون خيارات قائمة السياق)",
4747
"account.other-settings.llm.default_llm": "نموذج اللغة الافتراضي AI",
4848
"account.other-settings.llm.disable_all": "<strong>تعطيل جميع تكاملات الذكاء الاصطناعي</strong>، مثل أزرار توليد أو شرح الأكواد في Jupyter، وذكر @chatgpt، إلخ.",
49+
"account.other-settings.llm.reply_language": "<strong>الرد دائمًا باللغة الإنجليزية:</strong> إذا تم التعيين، تكون الردود دائمًا باللغة الإنجليزية. وإلا، فإنه يرد بلغتك ({lang}).",
4950
"account.other-settings.llm.title": "إعدادات AI",
5051
"account.other-settings.markdown_codebar": "<strong>تعطيل شريط كود العلامات</strong> في جميع مستندات العلامات. يؤدي تحديد هذا إلى إخفاء أزرار التشغيل والنسخ والشرح الإضافية في كتل الكود المسورة.",
5152
"account.other-settings.mask_files": "<strong>إخفاء الملفات:</strong> تظليل الملفات في عارض الملفات التي ربما لا تريد فتحها",
@@ -600,6 +601,7 @@
600601
"labels.connection": "الاتصال",
601602
"labels.copied": "تم النسخ",
602603
"labels.copy": "نسخ",
604+
"labels.create": "إنشاء",
603605
"labels.create_project": "إنشاء مشروع...",
604606
"labels.created": "تم الإنشاء",
605607
"labels.created_file": "تم الإنشاء",
@@ -621,7 +623,7 @@
621623
"labels.idle_timeout": "مهلة الخمول",
622624
"labels.insert": "إدراج",
623625
"labels.language": "اللغة",
624-
"labels.latex_document": "مستند LaTeX",
626+
"labels.latex_document": "LaTeX",
625627
"labels.license": "رخصة",
626628
"labels.licenses": "التراخيص",
627629
"labels.line_numbers": "أرقام الأسطر",
@@ -887,14 +889,16 @@
887889
"project.settings.control.idle_timeout.always_running.info": "سيتم <b>تشغيل المشروع تلقائيًا</b> إذا توقف لأي سبب (سيقوم بتشغيل أي <A>برامج تهيئة</A>).",
888890
"project.settings.control.idle_timeout.info": "<b>حول {ago}</b> سيتوقف المشروع ما لم يقم شخص ما بتحريره بنشاط.",
889891
"project.settings.control.uptime.info": "المشروع بدأ <b>{ago}</b> منذ",
892+
"project.settings.hide-delete-box.delete.confirm.yes": "نعم، يرجى حذف هذا المشروع!",
890893
"project.settings.hide-delete-box.delete.disclaimer": "المشاريع لا تُحذف فورًا. إذا كنت بحاجة إلى حذف بعض المعلومات الحساسة بشكل دائم وفوري في هذا المشروع، اتصل بـ {help}",
891894
"project.settings.hide-delete-box.delete.explanation": "حذف هذا المشروع للجميع. يمكنك التراجع عن هذا لبضعة أيام وبعدها يصبح دائمًا ويتم فقدان جميع البيانات في هذا المشروع. تتوقف أي خوادم حساب جارية بعد فترة قصيرة من حذف المشروع، وسيتم حذف خوادم الحساب بشكل دائم خلال بضعة أيام إذا لم يتم استعادة المشروع.",
892-
"project.settings.hide-delete-box.delete.label": "{is_deleted, select, true {استعادة المشروع} other {حذف المشروع...}} مشروع",
895+
"project.settings.hide-delete-box.delete.label": "{is_deleted, select, true {استعادة المشروع} other {حذف المشروع}}",
893896
"project.settings.hide-delete-box.delete.warning.confirmation": "نعم، يرجى حذف هذا المشروع",
894897
"project.settings.hide-delete-box.delete.warning.info": "سيتم إزالة جميع الترقيات الخاصة بك من هذا المشروع تلقائيًا. لن يؤدي استعادة المشروع إلى استعادتها تلقائيًا. لن يؤثر هذا على الترقيات التي طبقها الآخرون.",
895898
"project.settings.hide-delete-box.delete.warning.title": "هل أنت متأكد أنك تريد حذف هذا المشروع؟",
896899
"project.settings.hide-delete-box.hide.explanation": "{hide, select, true { أظهر هذا المشروع، بحيث يظهر في قائمة المشاريع الافتراضية الخاصة بك. في الوقت الحالي، يظهر فقط عند تحديد المخفي. } other { أخفِ هذا المشروع، بحيث لا يظهر في قائمة المشاريع الافتراضية الخاصة بك. هذا يؤثر عليك فقط، وليس على المتعاونين معك، ويمكنك بسهولة إظهاره. }}",
897-
"project.settings.hide-delete-box.hide.label": "{hidden, select, true {إظهار} other {إخفاء}} مشروع",
900+
"project.settings.hide-delete-box.hide.label": "{hidden, select, true {إظهار المشروع} other {إخفاء المشروع}}",
901+
"project.settings.hide-delete-box.hide.switch": "{hidden, select, true {مخفي} other {مرئي}}",
898902
"project.settings.hide-delete-box.title": "إخفاء أو حذف المشروع",
899903
"project.settings.restart-project.button.label": "{is_running, select, true {إعادة التشغيل} other {بدء}}",
900904
"project.settings.site-license.button.label": "الترقية باستخدام مفتاح الترخيص...",

0 commit comments

Comments
 (0)