mirror of
https://github.com/mastodon/mastodon.git
synced 2025-07-15 16:58:14 +00:00
Merge 796bcc701d
into 3b52dca405
This commit is contained in:
commit
ec386eba6a
|
@ -15,7 +15,6 @@ import { missingAltTextModal } from 'mastodon/initial_state';
|
|||
import AutosuggestInput from 'mastodon/components/autosuggest_input';
|
||||
import AutosuggestTextarea from 'mastodon/components/autosuggest_textarea';
|
||||
import { Button } from 'mastodon/components/button';
|
||||
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
|
||||
import EmojiPickerDropdown from '../containers/emoji_picker_dropdown_container';
|
||||
import PollButtonContainer from '../containers/poll_button_container';
|
||||
import PrivacyDropdownContainer from '../containers/privacy_dropdown_container';
|
||||
|
|
|
@ -20,7 +20,7 @@ import { languages as preloadedLanguages } from 'mastodon/initial_state';
|
|||
import type { RootState } from 'mastodon/store';
|
||||
import { useAppSelector, useAppDispatch } from 'mastodon/store';
|
||||
|
||||
import { debouncedGuess } from '../util/language_detection';
|
||||
import { debouncedGuess, countLetters } from '../util/language_detection';
|
||||
|
||||
const messages = defineMessages({
|
||||
changeLanguage: {
|
||||
|
@ -375,12 +375,25 @@ export const LanguageDropdown: React.FC = () => {
|
|||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (text.length > 20) {
|
||||
debouncedGuess(text, setGuess);
|
||||
let canceled = false;
|
||||
|
||||
if (countLetters(text) >= 5) {
|
||||
debouncedGuess(text)
|
||||
.then((lang) => {
|
||||
if (!canceled) {
|
||||
setGuess(lang ?? '');
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
setGuess('');
|
||||
});
|
||||
} else {
|
||||
debouncedGuess.cancel();
|
||||
setGuess('');
|
||||
}
|
||||
|
||||
return () => {
|
||||
canceled = true;
|
||||
};
|
||||
}, [text, setGuess]);
|
||||
|
||||
return (
|
||||
|
|
5
app/javascript/mastodon/features/compose/util/language_detection.d.ts
vendored
Normal file
5
app/javascript/mastodon/features/compose/util/language_detection.d.ts
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
export declare const debouncedGuess: (
|
||||
text: string,
|
||||
) => Promise<string | undefined>;
|
||||
|
||||
export declare const countLetters: (text: string) => number;
|
|
@ -1,7 +1,5 @@
|
|||
import lande from 'lande';
|
||||
import { debounce } from 'lodash';
|
||||
|
||||
import { urlRegex } from './url_regex';
|
||||
const languageDetectorInGlobalThis = 'LanguageDetector' in globalThis;
|
||||
let languageDetectorSupportedAndReady = languageDetectorInGlobalThis && await globalThis.LanguageDetector.availability() === 'available';
|
||||
|
||||
const ISO_639_MAP = {
|
||||
afr: 'af', // Afrikaans
|
||||
|
@ -56,21 +54,23 @@ const ISO_639_MAP = {
|
|||
vie: 'vi', // Vietnamese
|
||||
};
|
||||
|
||||
const guessLanguage = (text) => {
|
||||
text = text
|
||||
.replace(urlRegex, '')
|
||||
.replace(/(^|[^/\w])@(([a-z0-9_]+)@[a-z0-9.-]+[a-z0-9]+)/ig, '');
|
||||
|
||||
if (text.length > 20) {
|
||||
const [lang, confidence] = lande(text)[0];
|
||||
|
||||
if (confidence > 0.8)
|
||||
return ISO_639_MAP[lang];
|
||||
}
|
||||
|
||||
return '';
|
||||
const countLetters = (text) => {
|
||||
const segmenter = new Intl.Segmenter('und', { granularity: 'grapheme' })
|
||||
const letters = [...segmenter.segment(text)]
|
||||
return letters.length
|
||||
};
|
||||
|
||||
export const debouncedGuess = debounce((text, setGuess) => {
|
||||
setGuess(guessLanguage(text));
|
||||
}, 500, { maxWait: 1500, leading: true, trailing: true });
|
||||
let module;
|
||||
// If the API is supported, but the model not loaded yet…
|
||||
if (languageDetectorInGlobalThis) {
|
||||
if (!languageDetectorSupportedAndReady) {
|
||||
// …trigger the model download
|
||||
globalThis.LanguageDetector.create();
|
||||
}
|
||||
module = await import('./language_detection_with_languagedetector');
|
||||
} else {
|
||||
module = await import('./language_detection_with_laude');
|
||||
}
|
||||
const debouncedGuess = module.debouncedGuess;
|
||||
|
||||
export { debouncedGuess, countLetters, ISO_639_MAP };
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
import { debounce } from 'lodash';
|
||||
|
||||
import { urlRegex } from './url_regex';
|
||||
|
||||
const guessLanguage = async (text) => {
|
||||
text = text
|
||||
.replace(urlRegex, '')
|
||||
.replace(/(^|[^/\w])@(([a-z0-9_]+)@[a-z0-9.-]+[a-z0-9]+)/ig, '');
|
||||
|
||||
try {
|
||||
const languageDetector = await globalThis.LanguageDetector.create();
|
||||
let {detectedLanguage, confidence} = (await languageDetector.detect(text))[0];
|
||||
if (confidence > 0.8) {
|
||||
detectedLanguage = detectedLanguage.split('-')[0];
|
||||
return detectedLanguage;
|
||||
}
|
||||
} catch {
|
||||
return '';
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
const debouncedGuess = (() => {
|
||||
let resolver = null;
|
||||
|
||||
const debounced = debounce((text) => {
|
||||
const result = guessLanguage(text);
|
||||
if (resolver) {
|
||||
resolver(result);
|
||||
resolver = null;
|
||||
}
|
||||
}, 500, { maxWait: 1500, leading: true, trailing: true });
|
||||
|
||||
return (text) => new Promise((resolve) => {
|
||||
resolver = resolve;
|
||||
debounced(text);
|
||||
});
|
||||
})();
|
||||
|
||||
export { debouncedGuess };
|
|
@ -0,0 +1,38 @@
|
|||
import lande from 'lande';
|
||||
import { debounce } from 'lodash';
|
||||
|
||||
import { countLetters, ISO_639_MAP } from './language_detection';
|
||||
import { urlRegex } from './url_regex';
|
||||
|
||||
const guessLanguage = (text) => {
|
||||
text = text
|
||||
.replace(urlRegex, '')
|
||||
.replace(/(^|[^/\w])@(([a-z0-9_]+)@[a-z0-9.-]+[a-z0-9]+)/ig, '');
|
||||
|
||||
if (countLetters(text) > 20) {
|
||||
const [lang, confidence] = lande(text)[0];
|
||||
if (confidence > 0.8)
|
||||
return ISO_639_MAP[lang];
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
|
||||
const debouncedGuess = (() => {
|
||||
let resolver = null;
|
||||
|
||||
const debounced = debounce((text) => {
|
||||
const result = guessLanguage(text);
|
||||
if (resolver) {
|
||||
resolver(result);
|
||||
resolver = null;
|
||||
}
|
||||
}, 500, { maxWait: 1500, leading: true, trailing: true });
|
||||
|
||||
return (text) => new Promise((resolve) => {
|
||||
resolver = resolve;
|
||||
debounced(text);
|
||||
});
|
||||
})();
|
||||
|
||||
export { debouncedGuess };
|
Loading…
Reference in New Issue
Block a user