зеркало из https://github.com/mozilla/pontoon.git
Fix Bug 1696517 - Upgrade flow to 0.146.0 (#1888)
Co-authored-by: Axel Hecht <axel@pike.org>
This commit is contained in:
Родитель
fbf931b665
Коммит
72f172a9b6
|
@ -59,6 +59,8 @@ module.exports = {
|
|||
SyntheticMouseEvent: false,
|
||||
TimeoutID: false,
|
||||
"$Diff": false,
|
||||
"$ReadOnlyArray": false,
|
||||
"React$Element": false,
|
||||
},
|
||||
plugins: [
|
||||
'react',
|
||||
|
|
|
@ -10,9 +10,7 @@
|
|||
module.system=node
|
||||
module.system.node.resolve_dirname=node_modules
|
||||
module.system.node.resolve_dirname=./src
|
||||
|
||||
# This is used to ignore some Flow errors if needed.
|
||||
suppress_comment= \\(.\\|\n\\)*\\$FLOW_FIXME
|
||||
suppress_comment= \\(.\\|\n\\)*\\$FLOW_IGNORE
|
||||
module.name_mapper='^core\(.*\)$' -> '<PROJECT_ROOT>/src/core/\1'
|
||||
module.name_mapper='^modules\(.*\)$' -> '<PROJECT_ROOT>/src/modules/\1'
|
||||
|
||||
[strict]
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
declare module '@fluent/react' {
|
||||
declare export class ReactLocalization {
|
||||
constructor(Array<any>): ReactLocalization;
|
||||
}
|
||||
|
||||
declare export function LocalizationProvider(
|
||||
props: any,
|
||||
): React$Element<any>;
|
||||
|
||||
declare export interface LocalizedProps {
|
||||
id: string;
|
||||
attrs?: { [string]: boolean };
|
||||
children?: React$Node;
|
||||
vars?: { [string]: any };
|
||||
elems?: { [string]: ?React$Element<any> };
|
||||
}
|
||||
declare export function Localized(
|
||||
props: LocalizedProps,
|
||||
): React$Element<any>;
|
||||
}
|
||||
|
||||
declare module 'react-content-marker' {
|
||||
declare export type TagFunction = (input: string) => React$Element<any>;
|
||||
declare export interface Parser {
|
||||
rule: string | RegExp;
|
||||
tag: TagFunction;
|
||||
matchIndex?: number;
|
||||
}
|
||||
declare export default function createMarker(parsers: Array<Parser>): any;
|
||||
declare export function mark(
|
||||
content: string | Array<React$Node>,
|
||||
rule: string | RegExp,
|
||||
tag: TagFunction,
|
||||
matchIndex?: number,
|
||||
): Array<React$Node>;
|
||||
}
|
|
@ -11,7 +11,7 @@
|
|||
"connected-react-router": "6.8.0",
|
||||
"date-and-time": "0.14.2",
|
||||
"diff-match-patch": "1.0.4",
|
||||
"flow-bin": "0.95.1",
|
||||
"flow-bin": "0.146.0",
|
||||
"highcharts": "7.2.2",
|
||||
"highcharts-react-official": "2.2.2",
|
||||
"html-react-parser": "0.13.0",
|
||||
|
|
|
@ -150,4 +150,4 @@ const mapStateToProps = (state: Object): Props => {
|
|||
};
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps)(App);
|
||||
export default (connect(mapStateToProps)(App): any);
|
||||
|
|
|
@ -34,13 +34,13 @@ export default class APIBase {
|
|||
return new URL(url, window.location.origin);
|
||||
}
|
||||
|
||||
toCamelCase = (s: string) => {
|
||||
toCamelCase: (s: string) => string = (s: string) => {
|
||||
return s.replace(/([-_][a-z])/gi, ($1) => {
|
||||
return $1.toUpperCase().replace('-', '').replace('_', '');
|
||||
});
|
||||
};
|
||||
|
||||
isObject = function (obj: any) {
|
||||
isObject: (obj: any) => boolean = function (obj: any) {
|
||||
return (
|
||||
obj === Object(obj) &&
|
||||
!Array.isArray(obj) &&
|
||||
|
@ -96,7 +96,7 @@ export default class APIBase {
|
|||
}
|
||||
}
|
||||
|
||||
keysToCamelCase(results: any) {
|
||||
keysToCamelCase(results: any): any {
|
||||
if (this.isObject(results)) {
|
||||
const newObj: any = {};
|
||||
|
||||
|
|
|
@ -3,7 +3,12 @@
|
|||
import APIBase from './base';
|
||||
|
||||
export default class CommentAPI extends APIBase {
|
||||
add(entity: number, locale: string, comment: string, translation: ?number) {
|
||||
add(
|
||||
entity: number,
|
||||
locale: string,
|
||||
comment: string,
|
||||
translation: ?number,
|
||||
): Promise<any> {
|
||||
const payload = new URLSearchParams();
|
||||
payload.append('entity', entity.toString());
|
||||
payload.append('locale', locale);
|
||||
|
@ -20,7 +25,7 @@ export default class CommentAPI extends APIBase {
|
|||
return this.fetch('/add-comment/', 'POST', payload, headers);
|
||||
}
|
||||
|
||||
_updateComment(url: string, commentId: number) {
|
||||
_updateComment(url: string, commentId: number): Promise<any> {
|
||||
const payload = new URLSearchParams();
|
||||
payload.append('comment_id', commentId.toString());
|
||||
|
||||
|
@ -32,11 +37,11 @@ export default class CommentAPI extends APIBase {
|
|||
return this.fetch(url, 'POST', payload, headers);
|
||||
}
|
||||
|
||||
pinComment(commentId: number) {
|
||||
pinComment(commentId: number): Promise<any> {
|
||||
return this._updateComment('/pin-comment/', commentId);
|
||||
}
|
||||
|
||||
unpinComment(commentId: number) {
|
||||
unpinComment(commentId: number): Promise<any> {
|
||||
return this._updateComment('/unpin-comment/', commentId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ export default class EntityAPI extends APIBase {
|
|||
entities: Array<number>,
|
||||
find: ?string,
|
||||
replace: ?string,
|
||||
) {
|
||||
): Promise<any> {
|
||||
const payload = new FormData();
|
||||
|
||||
const csrfToken = this.getCSRFToken();
|
||||
|
@ -116,7 +116,11 @@ export default class EntityAPI extends APIBase {
|
|||
return await this.fetch('/get-entities/', 'POST', payload, headers);
|
||||
}
|
||||
|
||||
async getHistory(entity: number, locale: string, pluralForm: number = -1) {
|
||||
async getHistory(
|
||||
entity: number,
|
||||
locale: string,
|
||||
pluralForm: number = -1,
|
||||
): Promise<any> {
|
||||
const payload = new URLSearchParams();
|
||||
payload.append('entity', entity.toString());
|
||||
payload.append('locale', locale);
|
||||
|
@ -160,7 +164,7 @@ export default class EntityAPI extends APIBase {
|
|||
return results;
|
||||
}
|
||||
|
||||
async getTeamComments(entity: number, locale: string) {
|
||||
async getTeamComments(entity: number, locale: string): Promise<any> {
|
||||
const payload = new URLSearchParams();
|
||||
payload.append('entity', entity.toString());
|
||||
payload.append('locale', locale);
|
||||
|
@ -178,7 +182,7 @@ export default class EntityAPI extends APIBase {
|
|||
return this.keysToCamelCase(results);
|
||||
}
|
||||
|
||||
async getTerms(sourceString: string, locale: string) {
|
||||
async getTerms(sourceString: string, locale: string): Promise<any> {
|
||||
const payload = new URLSearchParams();
|
||||
payload.append('source_string', sourceString);
|
||||
payload.append('locale', locale);
|
||||
|
|
|
@ -6,7 +6,7 @@ export default class FilterAPI extends APIBase {
|
|||
/**
|
||||
* Return data needed for filtering strings.
|
||||
*/
|
||||
async get(locale: string, project: string, resource: string) {
|
||||
async get(locale: string, project: string, resource: string): Promise<any> {
|
||||
const headers = new Headers();
|
||||
headers.append('X-Requested-With', 'XMLHttpRequest');
|
||||
|
||||
|
|
|
@ -29,14 +29,14 @@ export type {
|
|||
} from './types';
|
||||
|
||||
export default {
|
||||
entity: new EntityAPI(),
|
||||
comment: new CommentAPI(),
|
||||
filter: new FilterAPI(),
|
||||
locale: new LocaleAPI(),
|
||||
l10n: new L10nAPI(),
|
||||
machinery: new MachineryAPI(),
|
||||
project: new ProjectAPI(),
|
||||
resource: new ResourceAPI(),
|
||||
translation: new TranslationAPI(),
|
||||
user: new UserAPI(),
|
||||
entity: (new EntityAPI(): EntityAPI),
|
||||
comment: (new CommentAPI(): CommentAPI),
|
||||
filter: (new FilterAPI(): FilterAPI),
|
||||
locale: (new LocaleAPI(): LocaleAPI),
|
||||
l10n: (new L10nAPI(): L10nAPI),
|
||||
machinery: (new MachineryAPI(): MachineryAPI),
|
||||
project: (new ProjectAPI(): ProjectAPI),
|
||||
resource: (new ResourceAPI(): ResourceAPI),
|
||||
translation: (new TranslationAPI(): TranslationAPI),
|
||||
user: (new UserAPI(): UserAPI),
|
||||
};
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
import APIBase from './base';
|
||||
|
||||
export default class L10nAPI extends APIBase {
|
||||
async get(locale: string) {
|
||||
async get(locale: string): Promise<string> {
|
||||
const url = this.getFullURL(`/static/locale/${locale}/translate.ftl`);
|
||||
const response = await fetch(url);
|
||||
return await response.text();
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
import APIBase from './base';
|
||||
|
||||
export default class LocaleAPI extends APIBase {
|
||||
async get(code: string) {
|
||||
async get(code: string): Promise<any> {
|
||||
const query = `{
|
||||
locale(code: "${code}") {
|
||||
code
|
||||
|
|
|
@ -12,7 +12,7 @@ type ConcordanceTranslations = {|
|
|||
|};
|
||||
|
||||
export default class MachineryAPI extends APIBase {
|
||||
async _get(url: string, params: Object) {
|
||||
async _get(url: string, params: Object): Promise<any> {
|
||||
const payload = new URLSearchParams();
|
||||
for (let param in params) {
|
||||
payload.append(param, params[param]);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
import APIBase from './base';
|
||||
|
||||
export default class ProjectAPI extends APIBase {
|
||||
async get(slug: string) {
|
||||
async get(slug: string): Promise<any> {
|
||||
const query = `{
|
||||
project(slug: "${slug}") {
|
||||
slug
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
import APIBase from './base';
|
||||
|
||||
export default class ResourceAPI extends APIBase {
|
||||
async getAll(locale: string, project: string) {
|
||||
async getAll(locale: string, project: string): Promise<any> {
|
||||
const url = `/${locale}/${project}/parts/`;
|
||||
|
||||
const headers = new Headers();
|
||||
|
|
|
@ -20,7 +20,7 @@ export default class TranslationAPI extends APIBase {
|
|||
resource: string,
|
||||
ignoreWarnings: ?boolean,
|
||||
machinerySources: Array<SourceType>,
|
||||
) {
|
||||
): Promise<any> {
|
||||
const csrfToken = this.getCSRFToken();
|
||||
|
||||
const payload = new URLSearchParams();
|
||||
|
@ -58,7 +58,7 @@ export default class TranslationAPI extends APIBase {
|
|||
id: number,
|
||||
resource: string,
|
||||
ignoreWarnings: ?boolean,
|
||||
) {
|
||||
): Promise<any> {
|
||||
const csrfToken = this.getCSRFToken();
|
||||
|
||||
const payload = new URLSearchParams();
|
||||
|
@ -79,7 +79,11 @@ export default class TranslationAPI extends APIBase {
|
|||
return this.fetch(url, 'POST', payload, headers);
|
||||
}
|
||||
|
||||
approve(id: number, resource: string, ignoreWarnings: ?boolean) {
|
||||
approve(
|
||||
id: number,
|
||||
resource: string,
|
||||
ignoreWarnings: ?boolean,
|
||||
): Promise<any> {
|
||||
return this._changeStatus(
|
||||
'/translations/approve/',
|
||||
id,
|
||||
|
@ -88,19 +92,19 @@ export default class TranslationAPI extends APIBase {
|
|||
);
|
||||
}
|
||||
|
||||
unapprove(id: number, resource: string) {
|
||||
unapprove(id: number, resource: string): Promise<any> {
|
||||
return this._changeStatus('/translations/unapprove/', id, resource);
|
||||
}
|
||||
|
||||
reject(id: number, resource: string) {
|
||||
reject(id: number, resource: string): Promise<any> {
|
||||
return this._changeStatus('/translations/reject/', id, resource);
|
||||
}
|
||||
|
||||
unreject(id: number, resource: string) {
|
||||
unreject(id: number, resource: string): Promise<any> {
|
||||
return this._changeStatus('/translations/unreject/', id, resource);
|
||||
}
|
||||
|
||||
delete(id: number) {
|
||||
delete(id: number): Promise<any> {
|
||||
const payload = new URLSearchParams();
|
||||
payload.append('translation', id.toString());
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ type Props = {|
|
|||
resetContactPerson?: () => void,
|
||||
|};
|
||||
|
||||
export default function AddComment(props: Props) {
|
||||
export default function AddComment(props: Props): React.Element<'div'> {
|
||||
const {
|
||||
parameters,
|
||||
translation,
|
||||
|
@ -209,9 +209,9 @@ export default function AddComment(props: Props) {
|
|||
// This allows for the mention suggestions to stay properly positioned
|
||||
// when the container scrolls.
|
||||
React.useEffect(() => {
|
||||
// Flow does not recognize the event listeners with 'SyntheticEvent`,
|
||||
// so I'm ignoring the errors Flow throws here.
|
||||
// $FLOW_IGNORE
|
||||
// Flow does not recognize the addEventListener with 'SyntheticEvent` listeners,
|
||||
// so I'm ignoring the errors Flow throws below.
|
||||
|
||||
const handleScroll = (e: SyntheticEvent<HTMLElement>) => {
|
||||
const element = e.currentTarget;
|
||||
setScrollPosition(element.scrollTop);
|
||||
|
@ -225,17 +225,21 @@ export default function AddComment(props: Props) {
|
|||
}
|
||||
|
||||
if (historyScroll) {
|
||||
// $FlowIgnore
|
||||
historyScroll.addEventListener('scroll', handleScroll);
|
||||
}
|
||||
if (teamsScroll) {
|
||||
//$FlowIgnore
|
||||
teamsScroll.addEventListener('scroll', handleScroll);
|
||||
}
|
||||
|
||||
return () => {
|
||||
if (historyScroll) {
|
||||
// $FlowIgnore
|
||||
historyScroll.removeEventListener('scroll', handleScroll);
|
||||
}
|
||||
if (teamsScroll) {
|
||||
// $FlowIgnore
|
||||
teamsScroll.removeEventListener('scroll', handleScroll);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -18,7 +18,7 @@ type Props = {|
|
|||
togglePinnedStatus?: (boolean, number) => void,
|
||||
|};
|
||||
|
||||
export default function Comment(props: Props) {
|
||||
export default function Comment(props: Props): null | React.Element<'li'> {
|
||||
const { comment, canPin, togglePinnedStatus } = props;
|
||||
|
||||
if (!comment) {
|
||||
|
|
|
@ -25,7 +25,7 @@ type Props = {|
|
|||
resetContactPerson?: () => void,
|
||||
|};
|
||||
|
||||
export default function CommentsList(props: Props) {
|
||||
export default function CommentsList(props: Props): React.Element<'div'> {
|
||||
const {
|
||||
comments,
|
||||
parameters,
|
||||
|
|
|
@ -19,7 +19,7 @@ type Props = {|
|
|||
* Removed slices are wrapped in <del>.
|
||||
*/
|
||||
export default class TranslationDiff extends React.Component<Props> {
|
||||
render() {
|
||||
render(): React.Node {
|
||||
const { base, target } = this.props;
|
||||
return getDiff(base, target);
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import './components/TranslationDiff.css';
|
|||
|
||||
const dmp = new DiffMatchPatch();
|
||||
|
||||
export function getDiff(base: string, target: string) {
|
||||
export function getDiff(base: string, target: string): React.Node {
|
||||
const diff = dmp.diff_main(base, target);
|
||||
|
||||
dmp.diff_cleanupSemantic(diff);
|
||||
|
|
|
@ -23,7 +23,9 @@ type Props = {
|
|||
* Otherwise, if the "force suggestion" user setting is on, it renders "Suggest".
|
||||
* Otherwise, it renders "Save".
|
||||
*/
|
||||
export default function EditorMainAction(props: Props) {
|
||||
export default function EditorMainAction(
|
||||
props: Props,
|
||||
): React.Element<React.ElementType> {
|
||||
const isRunningRequest = useSelector(
|
||||
(state) => state.editor.isRunningRequest,
|
||||
);
|
||||
|
@ -51,7 +53,7 @@ export default function EditorMainAction(props: Props) {
|
|||
action: Function,
|
||||
title: string,
|
||||
label: string,
|
||||
glyph: ?React.Node,
|
||||
glyph: ?React.Element<'i'>,
|
||||
};
|
||||
|
||||
if (
|
||||
|
|
|
@ -30,7 +30,7 @@ type Props = {|
|
|||
* If the entity is read-only, shows a read-only notification.
|
||||
* Otherise, shows the various tools to control the editor.
|
||||
*/
|
||||
export default function EditorMenu(props: Props) {
|
||||
export default function EditorMenu(props: Props): React.Element<'menu'> {
|
||||
return (
|
||||
<menu className='editor-menu'>
|
||||
{props.firstItemHook}
|
||||
|
|
|
@ -28,7 +28,7 @@ export function EditorSettings({
|
|||
settings,
|
||||
toggleSetting,
|
||||
onDiscard,
|
||||
}: EditorSettingsProps) {
|
||||
}: EditorSettingsProps): React.Element<'ul'> {
|
||||
const ref = React.useRef(null);
|
||||
useOnDiscard(ref, onDiscard);
|
||||
|
||||
|
@ -89,13 +89,13 @@ export default class EditorSettingsBase extends React.Component<Props, State> {
|
|||
};
|
||||
}
|
||||
|
||||
toggleVisibility = () => {
|
||||
toggleVisibility: () => void = () => {
|
||||
this.setState((state) => {
|
||||
return { visible: !state.visible };
|
||||
});
|
||||
};
|
||||
|
||||
handleDiscard = () => {
|
||||
handleDiscard: () => void = () => {
|
||||
this.setState({
|
||||
visible: false,
|
||||
});
|
||||
|
@ -106,7 +106,7 @@ export default class EditorSettingsBase extends React.Component<Props, State> {
|
|||
this.toggleVisibility();
|
||||
}
|
||||
|
||||
render() {
|
||||
render(): React.Element<'div'> {
|
||||
return (
|
||||
<div className='editor-settings'>
|
||||
<div
|
||||
|
|
|
@ -20,7 +20,9 @@ type FailedChecksProps = {|
|
|||
* Shows a list of failed checks (errors and warnings) and a button to ignore
|
||||
* those checks and proceed anyway.
|
||||
*/
|
||||
export default function FailedChecks(props: FailedChecksProps) {
|
||||
export default function FailedChecks(
|
||||
props: FailedChecksProps,
|
||||
): null | React.Element<'div'> {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const errors = useSelector((state) => state.editor.errors);
|
||||
|
@ -91,7 +93,7 @@ export default function FailedChecks(props: FailedChecksProps) {
|
|||
}
|
||||
|
||||
type MainActionProps = {|
|
||||
source: number,
|
||||
source: string,
|
||||
user: UserState,
|
||||
isTranslator: boolean,
|
||||
errors: Array<string>,
|
||||
|
|
|
@ -231,19 +231,19 @@ export default class KeyboardShortcutsBase extends React.Component<
|
|||
};
|
||||
}
|
||||
|
||||
toggleVisibility = () => {
|
||||
toggleVisibility: () => void = () => {
|
||||
this.setState((state) => {
|
||||
return { visible: !state.visible };
|
||||
});
|
||||
};
|
||||
|
||||
handleDiscard = () => {
|
||||
handleDiscard: () => void = () => {
|
||||
this.setState({
|
||||
visible: false,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
render(): React.Element<'div'> {
|
||||
return (
|
||||
<div className='keyboard-shortcuts'>
|
||||
<Localized
|
||||
|
|
|
@ -19,7 +19,7 @@ type Props = {|
|
|||
* is provided for strings without HTML tags, so they need to be stripped.
|
||||
*/
|
||||
export default class TranslationLength extends React.Component<Props> {
|
||||
getLimit() {
|
||||
getLimit(): null | number {
|
||||
const { comment, format } = this.props;
|
||||
|
||||
if (format !== 'lang') {
|
||||
|
@ -44,7 +44,7 @@ export default class TranslationLength extends React.Component<Props> {
|
|||
|
||||
// Only used for countdown.
|
||||
// Source: https://stackoverflow.com/a/47140708
|
||||
stripHTML(translation: string) {
|
||||
stripHTML(translation: string): string {
|
||||
const doc = new DOMParser().parseFromString(translation, 'text/html');
|
||||
|
||||
if (!doc.body) {
|
||||
|
@ -54,7 +54,7 @@ export default class TranslationLength extends React.Component<Props> {
|
|||
return doc.body.textContent || '';
|
||||
}
|
||||
|
||||
render() {
|
||||
render(): React.Element<'div'> {
|
||||
const { original, translation } = this.props;
|
||||
|
||||
const limit = this.getLimit();
|
||||
|
|
|
@ -8,7 +8,10 @@ import { actions } from '..';
|
|||
/**
|
||||
* Return a function to add text to the content of the editor.
|
||||
*/
|
||||
export default function useAddTextToTranslation() {
|
||||
export default function useAddTextToTranslation(): (
|
||||
content: string,
|
||||
changeSource?: string,
|
||||
) => void {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return useCallback(
|
||||
|
|
|
@ -5,7 +5,7 @@ import useUpdateTranslation from './useUpdateTranslation';
|
|||
/**
|
||||
* Return a function to clear the content of the editor.
|
||||
*/
|
||||
export default function useClearEditor() {
|
||||
export default function useClearEditor(): () => void {
|
||||
const updateTranslation = useUpdateTranslation();
|
||||
|
||||
return () => {
|
||||
|
|
|
@ -15,7 +15,9 @@ import useUpdateTranslation from './useUpdateTranslation';
|
|||
/**
|
||||
* Return a function to copy the original translation into the editor.
|
||||
*/
|
||||
export default function useCopyMachineryTranslation() {
|
||||
export default function useCopyMachineryTranslation(): (
|
||||
translation: MachineryTranslation,
|
||||
) => void {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const addTextToTranslation = useAddTextToTranslation();
|
||||
|
|
|
@ -10,7 +10,7 @@ import useUpdateTranslation from './useUpdateTranslation';
|
|||
/**
|
||||
* Return a function to copy the original translation into the editor.
|
||||
*/
|
||||
export default function useCopyOriginalIntoEditor() {
|
||||
export default function useCopyOriginalIntoEditor(): () => void {
|
||||
const updateTranslation = useUpdateTranslation();
|
||||
|
||||
const entity = useSelector((state) =>
|
||||
|
|
|
@ -11,7 +11,9 @@ import useUpdateTranslation from './useUpdateTranslation';
|
|||
/**
|
||||
* Return a function to copy the other locale translation into the editor.
|
||||
*/
|
||||
export default function useCopyOtherLocaleTranslation() {
|
||||
export default function useCopyOtherLocaleTranslation(): (
|
||||
translation: OtherLocaleTranslation,
|
||||
) => void {
|
||||
const updateTranslation = useUpdateTranslation();
|
||||
const isReadOnlyEditor = useSelector((state) =>
|
||||
entities.selectors.isReadOnlyEditor(state),
|
||||
|
|
|
@ -9,7 +9,12 @@ import * as unsavedchanges from 'modules/unsavedchanges';
|
|||
/**
|
||||
* Return a function to handle shortcuts in a translation form.
|
||||
*/
|
||||
export default function useHandleShortcuts() {
|
||||
export default function useHandleShortcuts(): (
|
||||
event: SyntheticKeyboardEvent<HTMLTextAreaElement>,
|
||||
sendTranslation: (ignoreWarnings?: boolean, translation?: string) => void,
|
||||
clearEditorCustom?: () => void,
|
||||
copyOriginalIntoEditorCustom?: () => void,
|
||||
) => void {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const clearEditor = editor.useClearEditor();
|
||||
|
@ -143,7 +148,7 @@ export default function useHandleShortcuts() {
|
|||
}
|
||||
|
||||
const numTranslations =
|
||||
translations.length + (searchResults && searchResults.length);
|
||||
translations.length + (searchResults?.length || 0);
|
||||
if (!numTranslations) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,10 @@ import { actions } from '..';
|
|||
/**
|
||||
* Return a function to send a translation to the server.
|
||||
*/
|
||||
export default function useSendTranslation() {
|
||||
export default function useSendTranslation(): (
|
||||
ignoreWarnings?: boolean,
|
||||
content?: string,
|
||||
) => void {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const translation = useSelector((state) => state.editor.translation);
|
||||
|
|
|
@ -10,7 +10,10 @@ import type { Translation } from 'core/editor';
|
|||
/**
|
||||
* Return a function to update the content of the editor.
|
||||
*/
|
||||
export default function useUpdateTranslation() {
|
||||
export default function useUpdateTranslation(): (
|
||||
translation: Translation,
|
||||
changeSource?: string,
|
||||
) => void {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return useCallback(
|
||||
|
|
|
@ -14,7 +14,11 @@ import type { ChangeOperation } from 'modules/history';
|
|||
/**
|
||||
* Return a function to update the status (approved, rejected... ) of a translation.
|
||||
*/
|
||||
export default function useUpdateTranslationStatus() {
|
||||
export default function useUpdateTranslationStatus(): (
|
||||
translationId: number,
|
||||
change: ChangeOperation,
|
||||
ignoreWarnings: ?boolean,
|
||||
) => void {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const entity = useSelector((state) =>
|
||||
|
|
|
@ -31,7 +31,7 @@ export function _existingTranslation(
|
|||
(translation === initialTranslation ||
|
||||
// If translation is a FluentMessage, from the fluent editor.
|
||||
(translation.equals &&
|
||||
// $FLOW_IGNORE: `equals`, if defined, will always be a function.
|
||||
// $FlowIgnore: `equals`, if defined, will always be a function.
|
||||
translation.equals(initialTranslation)))
|
||||
) {
|
||||
existingTranslation = activeTranslation;
|
||||
|
@ -109,7 +109,7 @@ function _isFluentMessage(editorState: EditorState) {
|
|||
/**
|
||||
* Returns `true` if the current editor translation contains a Fluent message.
|
||||
*/
|
||||
const isFluentTranslationMessage = createSelector(
|
||||
const isFluentTranslationMessage: any = createSelector(
|
||||
editorSelector,
|
||||
_isFluentMessage,
|
||||
);
|
||||
|
|
|
@ -44,7 +44,7 @@ export function receive(localization: ReactLocalization): ReceiveAction {
|
|||
* This fetches the translations for the UI for each given locale, bundles
|
||||
* those and store them to be used in showing a localized interface.
|
||||
*/
|
||||
export function get(locales: Array<string>): Function {
|
||||
export function get(locales: $ReadOnlyArray<string>): Function {
|
||||
return async (dispatch) => {
|
||||
dispatch(request());
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ export class AppLocalizationProviderBase extends React.Component<InternalProps>
|
|||
this.props.dispatch(l10n.actions.get(locales));
|
||||
}
|
||||
|
||||
render() {
|
||||
render(): React.Element<React.ElementType> {
|
||||
const { children, l10n } = this.props;
|
||||
|
||||
return (
|
||||
|
@ -59,4 +59,4 @@ const mapStateToProps = (state: Object): Props => {
|
|||
};
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps)(AppLocalizationProviderBase);
|
||||
export default (connect(mapStateToProps)(AppLocalizationProviderBase): any);
|
||||
|
|
|
@ -63,11 +63,11 @@ function LightboxContent({ image, onClose }: ContentProps) {
|
|||
}
|
||||
|
||||
export class LightboxBase extends React.Component<InternalProps> {
|
||||
close = () => {
|
||||
close: () => void = () => {
|
||||
this.props.dispatch(close());
|
||||
};
|
||||
|
||||
render() {
|
||||
render(): null | React.Element<React.ElementType> {
|
||||
const { lightbox } = this.props;
|
||||
|
||||
if (!lightbox.isOpen) {
|
||||
|
@ -84,4 +84,4 @@ const mapStateToProps = (state: Object): Props => {
|
|||
};
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps)(LightboxBase);
|
||||
export default (connect(mapStateToProps)(LightboxBase): any);
|
||||
|
|
|
@ -32,7 +32,7 @@ export type Locale = {|
|
|||
export type RequestAction = {|
|
||||
type: typeof REQUEST,
|
||||
|};
|
||||
export function request() {
|
||||
export function request(): RequestAction {
|
||||
return {
|
||||
type: REQUEST,
|
||||
};
|
||||
|
@ -42,7 +42,7 @@ export type ReceiveAction = {|
|
|||
type: typeof RECEIVE,
|
||||
locale: Locale,
|
||||
|};
|
||||
export function receive(locale: Locale) {
|
||||
export function receive(locale: Locale): ReceiveAction {
|
||||
return {
|
||||
type: RECEIVE,
|
||||
locale,
|
||||
|
|
|
@ -16,7 +16,9 @@ import type { Locale } from './actions';
|
|||
* @param {Locale} locale A Locale object.
|
||||
* @returns {Object} A map of locale's cldrPlurals and their plural examples.
|
||||
*/
|
||||
export default function getPluralExamples(locale: Locale) {
|
||||
export default function getPluralExamples(
|
||||
locale: Locale,
|
||||
): { [number]: number } {
|
||||
const pluralsCount = locale.cldrPlurals.length;
|
||||
const examples = {};
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* @flow */
|
||||
|
||||
import { Localized } from '@fluent/react';
|
||||
import shortid from 'shortid';
|
||||
|
||||
export const ADD: 'notification/ADD' = 'notification/ADD';
|
||||
|
@ -14,7 +13,7 @@ export type NotificationType =
|
|||
|
||||
export type NotificationMessage = {|
|
||||
+type: NotificationType,
|
||||
+content: string | typeof Localized,
|
||||
+content: string | React$Element<any>,
|
||||
+key?: string,
|
||||
|};
|
||||
|
||||
|
|
|
@ -47,12 +47,12 @@ export default class NotificationPanel extends React.Component<Props, State> {
|
|||
}
|
||||
}
|
||||
|
||||
hide = () => {
|
||||
hide: () => void = () => {
|
||||
clearTimeout(this.hideTimeout);
|
||||
this.setState({ hiding: true });
|
||||
};
|
||||
|
||||
render() {
|
||||
render(): React.Element<'div'> {
|
||||
const { notification } = this.props;
|
||||
|
||||
let hideClass = '';
|
||||
|
|
|
@ -83,6 +83,6 @@ export const rules = [
|
|||
/**
|
||||
* Component that marks placeables in a string.
|
||||
*/
|
||||
const WithPlaceables = createMarker(rules);
|
||||
const WithPlaceables: any = createMarker(rules);
|
||||
|
||||
export default WithPlaceables;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* @flow */
|
||||
|
||||
import createMarker from 'react-content-marker';
|
||||
import type { Parser } from 'react-content-marker';
|
||||
|
||||
import './WithPlaceables.css';
|
||||
|
||||
|
@ -11,7 +12,7 @@ import fluentString from '../parsers/fluentString';
|
|||
import fluentTerm from '../parsers/fluentTerm';
|
||||
import multipleSpaces from '../parsers/multipleSpaces';
|
||||
|
||||
export function getRulesWithFluent(rules: Array<Object>) {
|
||||
export function getRulesWithFluent(rules: Array<Parser>): Array<Parser> {
|
||||
const newRules = [...rules];
|
||||
|
||||
// Insert after the last space-related rule.
|
||||
|
@ -31,6 +32,6 @@ export function getRulesWithFluent(rules: Array<Object>) {
|
|||
* The Fluent rules must come right after the space rules, otherwise it
|
||||
* generates a lot of false positives.
|
||||
*/
|
||||
const WithPlaceablesForFluent = createMarker(getRulesWithFluent(rules));
|
||||
const WithPlaceablesForFluent: any = createMarker(getRulesWithFluent(rules));
|
||||
|
||||
export default WithPlaceablesForFluent;
|
||||
|
|
|
@ -14,7 +14,7 @@ import { getRulesWithoutLeadingSpace } from './WithPlaceablesNoLeadingSpace';
|
|||
*
|
||||
* See ./WithPlaceablesNoLeadingSpace.js for documentation.
|
||||
*/
|
||||
const WithPlaceablesForFluentNoLeadingSpace = createMarker(
|
||||
const WithPlaceablesForFluentNoLeadingSpace: any = createMarker(
|
||||
getRulesWithFluent(getRulesWithoutLeadingSpace(rules)),
|
||||
);
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* @flow */
|
||||
|
||||
import createMarker from 'react-content-marker';
|
||||
import type { Parser } from 'react-content-marker';
|
||||
|
||||
import './WithPlaceables.css';
|
||||
|
||||
|
@ -8,7 +9,9 @@ import { rules } from './WithPlaceables';
|
|||
import leadingSpace from '../parsers/leadingSpace';
|
||||
import unusualSpace from '../parsers/unusualSpace';
|
||||
|
||||
export function getRulesWithoutLeadingSpace(rules: Array<Object>) {
|
||||
export function getRulesWithoutLeadingSpace(
|
||||
rules: Array<Parser>,
|
||||
): Array<Parser> {
|
||||
let newRules = [...rules];
|
||||
newRules.splice(newRules.indexOf(leadingSpace), 1);
|
||||
newRules.splice(newRules.indexOf(unusualSpace), 1);
|
||||
|
@ -26,7 +29,7 @@ export function getRulesWithoutLeadingSpace(rules: Array<Object>) {
|
|||
* have a special Placeables component without that parser, for use in
|
||||
* combination with other parsing tools (like diff).
|
||||
*/
|
||||
const WithPlaceablesNoLeadingSpace = createMarker(
|
||||
const WithPlaceablesNoLeadingSpace: any = createMarker(
|
||||
getRulesWithoutLeadingSpace(rules),
|
||||
);
|
||||
|
||||
|
|
|
@ -15,8 +15,8 @@ import { Localized } from '@fluent/react';
|
|||
* https://github.com/translate/translate/blob/2.3.1/translate/storage/placeables/general.py#L55
|
||||
*/
|
||||
const altAttribute = {
|
||||
rule: /(alt=".*?")/i,
|
||||
tag: (x: string) => {
|
||||
rule: (/(alt=".*?")/i: RegExp),
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-altAttribute'
|
||||
|
|
|
@ -16,9 +16,9 @@ import { Localized } from '@fluent/react';
|
|||
* https://github.com/translate/translate/blob/2.3.1/translate/storage/placeables/general.py#L274
|
||||
*/
|
||||
const camelCaseString = {
|
||||
rule: /(\b([a-z]+[A-Z]|[A-Z]+[a-z]+[A-Z]|[A-Z]{2,}[a-z])[a-zA-Z0-9]*\b)/,
|
||||
rule: (/(\b([a-z]+[A-Z]|[A-Z]+[a-z]+[A-Z]|[A-Z]{2,}[a-z])[a-zA-Z0-9]*\b)/: RegExp),
|
||||
matchIndex: 0,
|
||||
tag: (x: string) => {
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-camelCaseString'
|
||||
|
|
|
@ -16,9 +16,9 @@ import { Localized } from '@fluent/react';
|
|||
* https://github.com/translate/translate/blob/2.3.1/translate/storage/placeables/general.py#L220
|
||||
*/
|
||||
const emailPattern = {
|
||||
rule: /(((mailto:)|)[A-Za-z0-9]+[-a-zA-Z0-9._%]*@(([-A-Za-z0-9]+)\.)+[a-zA-Z]{2,4})/,
|
||||
rule: (/(((mailto:)|)[A-Za-z0-9]+[-a-zA-Z0-9._%]*@(([-A-Za-z0-9]+)\.)+[a-zA-Z]{2,4})/: RegExp),
|
||||
matchIndex: 0,
|
||||
tag: (x: string) => {
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-emailPattern'
|
||||
|
|
|
@ -8,7 +8,7 @@ import { Localized } from '@fluent/react';
|
|||
*/
|
||||
const escapeSequence = {
|
||||
rule: '\\',
|
||||
tag: (x: string) => {
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-escapeSequence'
|
||||
|
|
|
@ -16,9 +16,9 @@ import { Localized } from '@fluent/react';
|
|||
* https://github.com/translate/translate/blob/2.3.1/translate/storage/placeables/general.py#L208
|
||||
*/
|
||||
const filePattern = {
|
||||
rule: /(^|\s)((~\/|\/|\.\/)([-A-Za-z0-9_$.+!*(),;:@&=?/~#%]|\\){3,})/,
|
||||
rule: (/(^|\s)((~\/|\/|\.\/)([-A-Za-z0-9_$.+!*(),;:@&=?/~#%]|\\){3,})/: RegExp),
|
||||
matchIndex: 2,
|
||||
tag: (x: string) => {
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-filePattern'
|
||||
|
|
|
@ -15,8 +15,8 @@ import { Localized } from '@fluent/react';
|
|||
* { NUMBER($ratio, minimumFractionDigits: 2) }
|
||||
*/
|
||||
const fluentFunction = {
|
||||
rule: /({ ?[A-W0-9\-_]+[^}]* ?})/,
|
||||
tag: (x: string) => {
|
||||
rule: (/({ ?[A-W0-9\-_]+[^}]* ?})/: RegExp),
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-fluentFunction'
|
||||
|
|
|
@ -15,9 +15,9 @@ import { Localized } from '@fluent/react';
|
|||
* { -brand-name(foo-bar: "now that's a value!") }
|
||||
*/
|
||||
const fluentParametrizedTerm = {
|
||||
rule: /({ ?-[^}]*([^}]*: ?[^}]*) ?})/,
|
||||
rule: (/({ ?-[^}]*([^}]*: ?[^}]*) ?})/: RegExp),
|
||||
matchIndex: 1,
|
||||
tag: (x: string) => {
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-fluentParametrizedTerm'
|
||||
|
|
|
@ -14,8 +14,8 @@ import { Localized } from '@fluent/react';
|
|||
* { "Hello, World" }
|
||||
*/
|
||||
const fluentString = {
|
||||
rule: /({ ?"[^}]*" ?})/,
|
||||
tag: (x: string) => {
|
||||
rule: (/({ ?"[^}]*" ?})/: RegExp),
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-fluentString'
|
||||
|
|
|
@ -15,8 +15,8 @@ import { Localized } from '@fluent/react';
|
|||
* { -brand-name }
|
||||
*/
|
||||
const fluentTerm = {
|
||||
rule: /({ ?-[^}]* ?})/,
|
||||
tag: (x: string) => {
|
||||
rule: (/({ ?-[^}]* ?})/: RegExp),
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized id='placeable-parser-fluentTerm' attrs={{ title: true }}>
|
||||
<mark className='placeable' title='Fluent term'>
|
||||
|
|
|
@ -24,9 +24,9 @@ import { Localized } from '@fluent/react';
|
|||
* https://github.com/translate/translate/blob/2.3.1/translate/storage/placeables/general.py#L127
|
||||
*/
|
||||
const javaFormattingVariable = {
|
||||
rule: /({[0-9]+(,\s*(number(,\s*(integer|currency|percent|[-0#.,E;%\u2030\u00a4']+)?)?|(date|time)(,\s*(short|medium|long|full|.+?))?|choice,([^{]+({.+})?)+)?)?})/,
|
||||
rule: (/({[0-9]+(,\s*(number(,\s*(integer|currency|percent|[-0#.,E;%\u2030\u00a4']+)?)?|(date|time)(,\s*(short|medium|long|full|.+?))?|choice,([^{]+({.+})?)+)?)?})/: RegExp),
|
||||
matchIndex: 0,
|
||||
tag: (x: string) => {
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-javaFormattingVariable'
|
||||
|
|
|
@ -15,8 +15,8 @@ import { Localized } from '@fluent/react';
|
|||
* $FIRST_NAME$
|
||||
*/
|
||||
const jsonPlaceholder = {
|
||||
rule: /(\$[A-Z0-9_]+\$)/,
|
||||
tag: (x: string) => {
|
||||
rule: (/(\$[A-Z0-9_]+\$)/: RegExp),
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-jsonPlaceholder'
|
||||
|
|
|
@ -11,8 +11,8 @@ import { Localized } from '@fluent/react';
|
|||
* " Hello, world"
|
||||
*/
|
||||
const leadingSpace = {
|
||||
rule: /(^ +)/,
|
||||
tag: (x: string) => {
|
||||
rule: (/(^ +)/: RegExp),
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-leadingSpace'
|
||||
|
|
|
@ -7,8 +7,8 @@ import { Localized } from '@fluent/react';
|
|||
* Marks multiple consecutive spaces and replaces them with a middle dot.
|
||||
*/
|
||||
const multipleSpaces = {
|
||||
rule: /( +)/,
|
||||
tag: (x: string) => {
|
||||
rule: (/( +)/: RegExp),
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-multipleSpaces'
|
||||
|
|
|
@ -7,8 +7,8 @@ import { Localized } from '@fluent/react';
|
|||
* Marks the narrow no-break space character (Unicode U+202F).
|
||||
*/
|
||||
const narrowNonBreakingSpace = {
|
||||
rule: /([\u202F])/,
|
||||
tag: (x: string) => {
|
||||
rule: (/([\u202F])/: RegExp),
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-narrowNonBreakingSpace'
|
||||
|
|
|
@ -8,7 +8,7 @@ import { Localized } from '@fluent/react';
|
|||
*/
|
||||
const newlineCharacter = {
|
||||
rule: '\n',
|
||||
tag: (x: string) => {
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-newlineCharacter'
|
||||
|
|
|
@ -8,7 +8,7 @@ import { Localized } from '@fluent/react';
|
|||
*/
|
||||
const newlineEscape = {
|
||||
rule: '\\n',
|
||||
tag: (x: string) => {
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-newlineEscape'
|
||||
|
|
|
@ -8,7 +8,7 @@ import { Localized } from '@fluent/react';
|
|||
*/
|
||||
const nonBreakingSpace = {
|
||||
rule: '\u00A0',
|
||||
tag: (x: string) => {
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-nonBreakingSpace'
|
||||
|
|
|
@ -12,9 +12,9 @@ import { Localized } from '@fluent/react';
|
|||
* $BrandShortName
|
||||
*/
|
||||
const nsisVariable = {
|
||||
rule: /(^|\s)(\$[a-zA-Z][\w]*)/,
|
||||
rule: (/(^|\s)(\$[a-zA-Z][\w]*)/: RegExp),
|
||||
matchIndex: 2,
|
||||
tag: (x: string) => {
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-nsisVariable'
|
||||
|
|
|
@ -17,9 +17,9 @@ import { Localized } from '@fluent/react';
|
|||
* https://github.com/translate/translate/blob/2.3.1/translate/storage/placeables/general.py#L72
|
||||
*/
|
||||
const numberString = {
|
||||
rule: /([-+]?[0-9]+([\u00A0.,][0-9]+)*)\b/u,
|
||||
rule: (/([-+]?[0-9]+([\u00A0.,][0-9]+)*)\b/u: RegExp),
|
||||
matchIndex: 0,
|
||||
tag: (x: string) => {
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-numberString'
|
||||
|
|
|
@ -15,9 +15,9 @@ import { Localized } from '@fluent/react';
|
|||
* https://github.com/translate/translate/blob/2.3.1/translate/storage/placeables/general.py#L317
|
||||
*/
|
||||
const optionPattern = {
|
||||
rule: /(\B(-[a-zA-Z]|--[a-z-]+)\b)/,
|
||||
rule: (/(\B(-[a-zA-Z]|--[a-z-]+)\b)/: RegExp),
|
||||
matchIndex: 0,
|
||||
tag: (x: string) => {
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-optionPattern'
|
||||
|
|
|
@ -10,7 +10,7 @@ import { Localized } from '@fluent/react';
|
|||
* https://github.com/translate/translate/blob/2.3.1/translate/storage/placeables/general.py#L229
|
||||
*/
|
||||
const punctuation = {
|
||||
rule: new RegExp(
|
||||
rule: (new RegExp(
|
||||
'(' +
|
||||
'(' +
|
||||
/[™©®]|/.source + // Marks
|
||||
|
@ -25,9 +25,9 @@ const punctuation = {
|
|||
/[\u202F]/.source + // U202F - narrow no-break space
|
||||
')+' +
|
||||
')',
|
||||
),
|
||||
): RegExp),
|
||||
matchIndex: 0,
|
||||
tag: (x: string) => {
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-punctuation'
|
||||
|
|
|
@ -12,8 +12,8 @@ import { Localized } from '@fluent/react';
|
|||
* %(number)D
|
||||
*/
|
||||
const pythonFormatNamedString = {
|
||||
rule: /(%\([[\w\d!.,[\]%:$<>+\-= ]*\)[+|-|0\d+|#]?[.\d+]?[s|d|e|f|g|o|x|c|%])/i,
|
||||
tag: (x: string) => {
|
||||
rule: (/(%\([[\w\d!.,[\]%:$<>+\-= ]*\)[+|-|0\d+|#]?[.\d+]?[s|d|e|f|g|o|x|c|%])/i: RegExp),
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-pythonFormatNamedString'
|
||||
|
|
|
@ -16,8 +16,8 @@ import { Localized } from '@fluent/react';
|
|||
* {foo[42]}
|
||||
*/
|
||||
const pythonFormatString = {
|
||||
rule: /(\{{?[\w\d!.,[\]%:$<>+-= ]*\}?})/,
|
||||
tag: (x: string) => {
|
||||
rule: (/(\{{?[\w\d!.,[\]%:$<>+-= ]*\}?})/: RegExp),
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-pythonFormatString'
|
||||
|
|
|
@ -19,9 +19,9 @@ import { Localized } from '@fluent/react';
|
|||
* https://github.com/translate/translate/blob/2.3.1/translate/storage/placeables/general.py#L115
|
||||
*/
|
||||
const pythonFormattingVariable = {
|
||||
rule: /(%(%|(\([^)]+\)){0,1}[-+0#]{0,1}(\d+|\*){0,1}(\.(\d+|\*)){0,1}[hlL]{0,1}[diouxXeEfFgGcrs]{1}))/,
|
||||
rule: (/(%(%|(\([^)]+\)){0,1}[-+0#]{0,1}(\d+|\*){0,1}(\.(\d+|\*)){0,1}[hlL]{0,1}[diouxXeEfFgGcrs]{1}))/: RegExp),
|
||||
matchIndex: 0,
|
||||
tag: (x: string) => {
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-pythonFormattingVariable'
|
||||
|
|
|
@ -26,9 +26,9 @@ import { Localized } from '@fluent/react';
|
|||
* https://github.com/translate/translate/blob/2.3.1/translate/storage/placeables/general.py#L80
|
||||
*/
|
||||
const qtFormatting = {
|
||||
rule: /(%L?[1-9]\d{0,1}(?=([^\d]|$)))/,
|
||||
rule: (/(%L?[1-9]\d{0,1}(?=([^\d]|$)))/: RegExp),
|
||||
matchIndex: 0,
|
||||
tag: (x: string) => {
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-qtFormatting'
|
||||
|
|
|
@ -13,8 +13,8 @@ import { Localized } from '@fluent/react';
|
|||
* A4
|
||||
*/
|
||||
const shortCapitalNumberString = {
|
||||
rule: /(\b([A-Z][0-9])|([0-9][A-Z])\b)/,
|
||||
tag: (x: string) => {
|
||||
rule: (/(\b([A-Z][0-9])|([0-9][A-Z])\b)/: RegExp),
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-shortCapitalNumberString'
|
||||
|
|
|
@ -18,9 +18,9 @@ import { Localized } from '@fluent/react';
|
|||
* https://github.com/translate/translate/blob/2.3.1/translate/storage/placeables/general.py#L154
|
||||
*/
|
||||
const stringFormattingVariable = {
|
||||
rule: /(%(\d+\$)?[-+0#'I]?((\d+)|[*])?(\.\d+)?[hlI]?[cCdiouxXeEfgGnpsS])/,
|
||||
rule: (/(%(\d+\$)?[-+0#'I]?((\d+)|[*])?(\.\d+)?[hlI]?[cCdiouxXeEfgGnpsS])/: RegExp),
|
||||
matchIndex: 0,
|
||||
tag: (x: string) => {
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-stringFormattingVariable'
|
||||
|
|
|
@ -8,7 +8,7 @@ import { Localized } from '@fluent/react';
|
|||
*/
|
||||
const tabCharacter = {
|
||||
rule: '\t',
|
||||
tag: (x: string) => {
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-tabCharacter'
|
||||
|
|
|
@ -7,8 +7,8 @@ import { Localized } from '@fluent/react';
|
|||
* Marks the thin space character (Unicode U+2009).
|
||||
*/
|
||||
const thinSpace = {
|
||||
rule: /([\u2009])/,
|
||||
tag: (x: string) => {
|
||||
rule: (/([\u2009])/: RegExp),
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized id='placeable-parser-thinSpace' attrs={{ title: true }}>
|
||||
<mark className='placeable' title='Thin space'>
|
||||
|
|
|
@ -16,8 +16,8 @@ import { Localized } from '@fluent/react';
|
|||
* "hello world"
|
||||
*/
|
||||
const unusualSpace = {
|
||||
rule: /( +$|[\r\n\t]( +)| {2,})/,
|
||||
tag: (x: string) => {
|
||||
rule: (/( +$|[\r\n\t]( +)| {2,})/: RegExp),
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized
|
||||
id='placeable-parser-unusualSpace'
|
||||
|
|
|
@ -16,7 +16,7 @@ import { Localized } from '@fluent/react';
|
|||
* https://github.com/translate/translate/blob/2.3.1/translate/storage/placeables/general.py#L192
|
||||
*/
|
||||
const uriPattern = {
|
||||
rule: new RegExp(
|
||||
rule: (new RegExp(
|
||||
'(' +
|
||||
'(' +
|
||||
'(' +
|
||||
|
@ -31,9 +31,9 @@ const uriPattern = {
|
|||
/(?=$|\s|([\]'}>),"]))/.source +
|
||||
')',
|
||||
'i', // This one is not case sensitive.
|
||||
),
|
||||
): RegExp),
|
||||
matchIndex: 0,
|
||||
tag: (x: string) => {
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized id='placeable-parser-uriPattern' attrs={{ title: true }}>
|
||||
<mark className='placeable' title='URI'>
|
||||
|
|
|
@ -15,9 +15,9 @@ import { Localized } from '@fluent/react';
|
|||
* https://github.com/translate/translate/blob/2.3.1/translate/storage/placeables/general.py#L254
|
||||
*/
|
||||
const xmlEntity = {
|
||||
rule: /(&(([a-zA-Z][a-zA-Z0-9.-]*)|([#](\d{1,5}|x[a-fA-F0-9]{1,5})+));)/,
|
||||
rule: (/(&(([a-zA-Z][a-zA-Z0-9.-]*)|([#](\d{1,5}|x[a-fA-F0-9]{1,5})+));)/: RegExp),
|
||||
matchIndex: 0,
|
||||
tag: (x: string) => {
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized id='placeable-parser-xmlEntity' attrs={{ title: true }}>
|
||||
<mark className='placeable' title='XML entity'>
|
||||
|
|
|
@ -16,9 +16,9 @@ import { Localized } from '@fluent/react';
|
|||
* https://github.com/translate/translate/blob/2.3.1/translate/storage/placeables/general.py#L301
|
||||
*/
|
||||
const xmlTag = {
|
||||
rule: /(<[\w.:]+(\s([\w.:-]+=((".*?")|('.*?')))?)*\/?>|<\/[\w.]+>)/,
|
||||
rule: (/(<[\w.:]+(\s([\w.:-]+=((".*?")|('.*?')))?)*\/?>|<\/[\w.]+>)/: RegExp),
|
||||
matchIndex: 0,
|
||||
tag: (x: string) => {
|
||||
tag: (x: string): React.Element<React.ElementType> => {
|
||||
return (
|
||||
<Localized id='placeable-parser-xmlTag' attrs={{ title: true }}>
|
||||
<mark className='placeable' title='XML tag'>
|
||||
|
|
|
@ -28,7 +28,7 @@ export function moveToNextTranslation(
|
|||
export type ResetAction = {|
|
||||
type: typeof RESET,
|
||||
|};
|
||||
export function reset() {
|
||||
export function reset(): ResetAction {
|
||||
return {
|
||||
type: RESET,
|
||||
};
|
||||
|
@ -38,7 +38,7 @@ export type SelectAction = {|
|
|||
type: typeof SELECT,
|
||||
pluralForm: number,
|
||||
|};
|
||||
export function select(pluralForm: number) {
|
||||
export function select(pluralForm: number): SelectAction {
|
||||
return {
|
||||
type: SELECT,
|
||||
pluralForm,
|
||||
|
|
|
@ -58,7 +58,7 @@ export class PluralSelectorBase extends React.Component<InternalProps> {
|
|||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
render(): null | React.Element<'nav'> {
|
||||
const props = this.props;
|
||||
const { pluralForm } = props;
|
||||
|
||||
|
@ -96,7 +96,9 @@ export class PluralSelectorBase extends React.Component<InternalProps> {
|
|||
}
|
||||
}
|
||||
|
||||
export default function PluralSelector(props: WrapperProps) {
|
||||
export default function PluralSelector(
|
||||
props: WrapperProps,
|
||||
): React.Element<typeof PluralSelectorBase> {
|
||||
const state = {
|
||||
locale: useSelector((state) => state[locale.NAME]),
|
||||
pluralForm: useSelector((state) => selectors.getPluralForm(state)),
|
||||
|
|
|
@ -18,7 +18,7 @@ type Props = {|
|
|||
/**
|
||||
* Render a project menu item.
|
||||
*/
|
||||
export default function ProjectItem(props: Props) {
|
||||
export default function ProjectItem(props: Props): React.Element<'li'> {
|
||||
const { parameters, localization, navigateToPath } = props;
|
||||
const project = localization.project;
|
||||
const className = parameters.project === project.slug ? 'current' : null;
|
||||
|
|
|
@ -36,7 +36,7 @@ export function ProjectMenu({
|
|||
parameters,
|
||||
onDiscard,
|
||||
onNavigate,
|
||||
}: ProjectMenuProps) {
|
||||
}: ProjectMenuProps): React.Element<'div'> {
|
||||
// Searching
|
||||
const [search, setSearch] = React.useState('');
|
||||
|
||||
|
@ -193,19 +193,21 @@ export default class ProjectMenuBase extends React.Component<Props, State> {
|
|||
};
|
||||
}
|
||||
|
||||
toggleVisibility = () => {
|
||||
toggleVisibility: () => void = () => {
|
||||
this.setState((state) => {
|
||||
return { visible: !state.visible };
|
||||
});
|
||||
};
|
||||
|
||||
handleDiscard = () => {
|
||||
handleDiscard: () => void = () => {
|
||||
this.setState({
|
||||
visible: false,
|
||||
});
|
||||
};
|
||||
|
||||
navigateToPath = (event: SyntheticMouseEvent<HTMLAnchorElement>) => {
|
||||
navigateToPath: (event: SyntheticMouseEvent<HTMLAnchorElement>) => void = (
|
||||
event: SyntheticMouseEvent<HTMLAnchorElement>,
|
||||
) => {
|
||||
event.preventDefault();
|
||||
|
||||
const path = event.currentTarget.pathname;
|
||||
|
@ -216,7 +218,7 @@ export default class ProjectMenuBase extends React.Component<Props, State> {
|
|||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
render(): React.Element<'li'> {
|
||||
const { locale, parameters, project } = this.props;
|
||||
|
||||
if (parameters.project !== 'all-projects') {
|
||||
|
|
|
@ -13,7 +13,7 @@ type Props = {|
|
|||
/**
|
||||
* Render a project item percentage.
|
||||
*/
|
||||
export default function ProjectPercent(props: Props) {
|
||||
export default function ProjectPercent(props: Props): React.Element<'span'> {
|
||||
const {
|
||||
approvedStrings,
|
||||
stringsWithWarnings,
|
||||
|
|
|
@ -18,7 +18,7 @@ type Props = {|
|
|||
/**
|
||||
* Render a resource menu item.
|
||||
*/
|
||||
export default function ResourceItem(props: Props) {
|
||||
export default function ResourceItem(props: Props): React.Element<'li'> {
|
||||
const { parameters, resource, navigateToPath } = props;
|
||||
const className = parameters.resource === resource.path ? 'current' : null;
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ export function ResourceMenu({
|
|||
resources,
|
||||
onDiscard,
|
||||
onNavigate,
|
||||
}: ResourceMenuProps) {
|
||||
}: ResourceMenuProps): React.Element<'div'> {
|
||||
// Searching
|
||||
const [search, setSearch] = React.useState('');
|
||||
const resourceElements = resources.resources.filter(
|
||||
|
@ -216,19 +216,21 @@ export default class ResourceMenuBase extends React.Component<Props, State> {
|
|||
};
|
||||
}
|
||||
|
||||
toggleVisibility = () => {
|
||||
toggleVisibility: () => void = () => {
|
||||
this.setState((state) => {
|
||||
return { visible: !state.visible };
|
||||
});
|
||||
};
|
||||
|
||||
handleDiscard = () => {
|
||||
handleDiscard: () => void = () => {
|
||||
this.setState({
|
||||
visible: false,
|
||||
});
|
||||
};
|
||||
|
||||
navigateToPath = (event: SyntheticMouseEvent<HTMLAnchorElement>) => {
|
||||
navigateToPath: (event: SyntheticMouseEvent<HTMLAnchorElement>) => void = (
|
||||
event: SyntheticMouseEvent<HTMLAnchorElement>,
|
||||
) => {
|
||||
event.preventDefault();
|
||||
|
||||
const path = event.currentTarget.pathname;
|
||||
|
@ -239,7 +241,7 @@ export default class ResourceMenuBase extends React.Component<Props, State> {
|
|||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
render(): null | React.Element<'li'> {
|
||||
const { parameters, resources } = this.props;
|
||||
|
||||
if (parameters.project === 'all-projects') {
|
||||
|
|
|
@ -13,7 +13,7 @@ type Props = {|
|
|||
/**
|
||||
* Render a resource item percentage.
|
||||
*/
|
||||
export default function ResourcePercent(props: Props) {
|
||||
export default function ResourcePercent(props: Props): React.Element<'span'> {
|
||||
const {
|
||||
approvedStrings,
|
||||
stringsWithWarnings,
|
||||
|
|
|
@ -18,7 +18,7 @@ type Props = {|
|
|||
/**
|
||||
* Shows term entry with its metadata.
|
||||
*/
|
||||
export default function Term(props: Props) {
|
||||
export default function Term(props: Props): React.Element<React.ElementType> {
|
||||
const { isReadOnlyEditor, locale, term } = props;
|
||||
|
||||
const copyTermIntoEditor = (translation: string) => {
|
||||
|
|
|
@ -19,7 +19,7 @@ type Props = {|
|
|||
/**
|
||||
* Shows a list of terms.
|
||||
*/
|
||||
export default function TermsList(props: Props) {
|
||||
export default function TermsList(props: Props): React.Element<'ul'> {
|
||||
return (
|
||||
<ul className='terms-list'>
|
||||
{props.terms.map((term, i) => {
|
||||
|
|
|
@ -13,7 +13,7 @@ import {
|
|||
|
||||
import type { TermState } from 'core/term';
|
||||
|
||||
export default function getMarker(terms: TermState, forFluent: ?boolean) {
|
||||
export default function getMarker(terms: TermState, forFluent: ?boolean): any {
|
||||
let placeableRules = getRulesWithoutLeadingSpace(rules);
|
||||
|
||||
if (forFluent) {
|
||||
|
|
|
@ -12,18 +12,18 @@ import { withSearch } from 'modules/search';
|
|||
|
||||
import type { TranslationProps } from './GenericTranslation';
|
||||
|
||||
// $FLOW_IGNORE: I just can't get HOC working with Flow.
|
||||
// $FlowIgnore: I just can't get HOC working with Flow.
|
||||
const TranslationPlaceablesDiff = withDiff(
|
||||
WithPlaceablesForFluentNoLeadingSpace,
|
||||
);
|
||||
|
||||
// $FLOW_IGNORE: I just can't get HOC working with Flow.
|
||||
// $FlowIgnore: I just can't get HOC working with Flow.
|
||||
const TranslationPlaceablesSearch = withSearch(
|
||||
WithPlaceablesForFluentNoLeadingSpace,
|
||||
);
|
||||
|
||||
export default class FluentTranslation extends React.Component<TranslationProps> {
|
||||
render() {
|
||||
render(): React.Element<React.ElementType> {
|
||||
const { content, diffTarget, search } = this.props;
|
||||
|
||||
if (diffTarget) {
|
||||
|
|
|
@ -6,10 +6,10 @@ import { withDiff } from 'core/diff';
|
|||
import { WithPlaceables, WithPlaceablesNoLeadingSpace } from 'core/placeable';
|
||||
import { withSearch } from 'modules/search';
|
||||
|
||||
// $FLOW_IGNORE: I just can't get HOC working with Flow.
|
||||
// $FlowIgnore: I just can't get HOC working with Flow.
|
||||
const TranslationPlaceablesDiff = withDiff(WithPlaceablesNoLeadingSpace);
|
||||
|
||||
// $FLOW_IGNORE: I just can't get HOC working with Flow.
|
||||
// $FlowIgnore: I just can't get HOC working with Flow.
|
||||
const TranslationPlaceablesSearch = withSearch(WithPlaceablesNoLeadingSpace);
|
||||
|
||||
export type TranslationProps = {|
|
||||
|
@ -19,7 +19,7 @@ export type TranslationProps = {|
|
|||
|};
|
||||
|
||||
export default class GenericTranslation extends React.Component<TranslationProps> {
|
||||
render() {
|
||||
render(): React.Element<React.ElementType> {
|
||||
const { content, diffTarget, search } = this.props;
|
||||
|
||||
if (diffTarget) {
|
||||
|
|
|
@ -13,7 +13,7 @@ type Props = {|
|
|||
|};
|
||||
|
||||
export default class TranslationProxy extends React.Component<Props> {
|
||||
render() {
|
||||
render(): null | React.Element<React.ElementType> {
|
||||
const { content, diffTarget, format, search } = this.props;
|
||||
|
||||
if (!content) {
|
||||
|
|
|
@ -30,10 +30,10 @@ export function updateTourStatus(step: number): Function {
|
|||
};
|
||||
}
|
||||
|
||||
export type Settings = {
|
||||
export type Settings = {|
|
||||
runQualityChecks?: boolean,
|
||||
forceSuggestions?: boolean,
|
||||
};
|
||||
|};
|
||||
|
||||
/**
|
||||
* Update the user settings.
|
||||
|
|
|
@ -22,14 +22,14 @@ export default class FileUpload extends React.Component<Props> {
|
|||
this.uploadForm = React.createRef();
|
||||
}
|
||||
|
||||
submitForm = () => {
|
||||
submitForm: () => void = () => {
|
||||
const form = this.uploadForm.current;
|
||||
if (form) {
|
||||
form.submit();
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
render(): React.Element<'form'> {
|
||||
const { parameters } = this.props;
|
||||
|
||||
/* TODO: Refactor core.api.base and reuse getCSRFToken() here */
|
||||
|
|
|
@ -15,7 +15,7 @@ type Props = {|
|
|||
* Render a Sign In link styled as a button.
|
||||
*/
|
||||
export default class SignIn extends React.Component<Props> {
|
||||
render() {
|
||||
render(): React.Element<'span'> {
|
||||
return (
|
||||
<span className='user-signin'>
|
||||
<Localized id='user-SignIn--sign-in'>
|
||||
|
|
|
@ -11,7 +11,7 @@ type Props = {|
|
|||
* Render a link to the Sign In process.
|
||||
*/
|
||||
export default class SignInLink extends React.Component<Props> {
|
||||
generateSignInURL() {
|
||||
generateSignInURL(): string {
|
||||
const absoluteUrl = window.location.origin + this.props.url;
|
||||
const parsedUrl = new URL(absoluteUrl);
|
||||
const next = window.location.pathname + window.location.search;
|
||||
|
@ -21,7 +21,7 @@ export default class SignInLink extends React.Component<Props> {
|
|||
return parsedUrl.toString();
|
||||
}
|
||||
|
||||
render() {
|
||||
render(): React.Element<'a'> {
|
||||
return <a href={this.generateSignInURL()}>{this.props.children}</a>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,11 +11,11 @@ type Props = {|
|
|||
* Render a Sign Out link.
|
||||
*/
|
||||
export default class SignOut extends React.Component<Props> {
|
||||
signOut = () => {
|
||||
signOut: () => void = () => {
|
||||
this.props.signOut();
|
||||
};
|
||||
|
||||
render() {
|
||||
render(): React.Element<React.ElementType> {
|
||||
return (
|
||||
<Localized
|
||||
id='user-SignOut--sign-out'
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче