diff options
Diffstat (limited to 'extensions/TimedMediaHandler/MwEmbedModules/TimedText')
83 files changed, 3448 insertions, 0 deletions
diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/TimedText.config.php b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/TimedText.config.php new file mode 100644 index 00000000..46547697 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/TimedText.config.php @@ -0,0 +1,31 @@ +<?php + /** + * Do not edit this file instead use LocalSettings.php and + * $wgMwEmbedModuleConfig[ {configuration name} ] = value; format + */ + + return array( + // If the Timed Text interface should be displayed: + // 'always' Displays link and call to contribute always + // 'auto' Looks for child timed text elements or "apiTitleKey" & load interface + // 'off' Does not display the timed text interface + "TimedText.ShowInterface" => "auto", + + /** + * If the "add timed text" link / interface should be exposed + * allows usere to upload text files to the wiki + */ + 'TimedText.ShowAddTextLink' => false, + + // If the link to request a transcript should be shown on video files + 'TimedText.ShowRequestTranscript' => false, + + // The category for listing videos that need transcription: + 'TimedText.NeedsTranscriptCategory' => 'Videos needing subtitles', + + // The default bottom text padding + 'TimedText.BottomPadding' => 10, + + // Height of black box below video. + 'TimedText.BelowVideoBlackBoxHeight' => 40 + ); diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/TimedText.loader.js b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/TimedText.loader.js new file mode 100644 index 00000000..bbd62d0e --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/TimedText.loader.js @@ -0,0 +1,52 @@ +/** +* TimedText loader. +*/ +// Scope everything in "mw" ( keeps the global namespace clean ) +( function( mw, $ ) { + + /** + * Check if the video tags in the page support timed text + * this way we can add our timed text libraries to the player + * library request. + */ + // Update the player loader request with timedText library if the embedPlayer + // includes timedText tracks. + $( mw ).bind( 'EmbedPlayerUpdateDependencies', function( event, playerElement, classRequest ) { + if( mw.isTimedTextSupported( playerElement ) ) { + classRequest = $.merge( classRequest, ['mw.TimedText'] ); + } + } ); + // On new embed player check if we need to add timedText + $( mw ).bind( 'EmbedPlayerNewPlayer', function( event, embedPlayer ){ + if( mw.isTimedTextSupported( embedPlayer ) ){ + embedPlayer.timedText = new mw.TimedText( embedPlayer ); + } + }); + + /** + * Check timedText is active for a given embedPlayer + * @param {object} embedPlayer The player to be checked for timedText properties + */ + mw.isTimedTextSupported = function( embedPlayer ) { + //EmbedPlayerNewPlayer passes a div with data-mwprovider set, + //EmbedPlayerUpdateDependencies passes video element with data attribute + //catch both + var mwprovider = embedPlayer['data-mwprovider'] || $( embedPlayer ).data('mwprovider'); + var showInterface = mw.config.get( 'TimedText.ShowInterface.' + mwprovider ) || + mw.config.get( 'TimedText.ShowInterface' ); + + if ( showInterface == 'always' ) { + return true; + } else if ( showInterface == 'off' ) { + return false; + } + + // Check for standard 'track' attribute: + if ( $( embedPlayer ).find( 'track' ).length != 0 ) { + return true; + } else { + return false; + } + }; + +} )( mediaWiki, jQuery ); diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/TimedText.php b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/TimedText.php new file mode 100644 index 00000000..57f50043 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/TimedText.php @@ -0,0 +1,21 @@ +<?php + + // Register all the timedText modules + return array( + "mw.TimedText" => array( + 'scripts' => "resources/mw.TimedText.js", + 'styles' => "resources/mw.style.TimedText.css", + 'dependencies' => array( + 'mw.EmbedPlayer', + 'mw.TextSource' + ), + 'messageDir' => 'i18n', + ), + "mw.TextSource" => array( + 'scripts' => "resources/mw.TextSource.js", + 'dependencies' => array( + 'mediawiki.UtilitiesTime', + "mw.ajaxProxy", + ) + ) + ); diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/af.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/af.json new file mode 100644 index 00000000..0024412a --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/af.json @@ -0,0 +1,10 @@ +{ + "@metadata": { + "authors": [ + "Naudefj" + ] + }, + "mwe-timedtext-back-btn": "Terug", + "mwe-timedtext-textcat-cc": "Onderskrifte", + "mwe-timedtext-textcat-lrc": "Lirieke" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ar.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ar.json new file mode 100644 index 00000000..48597e00 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ar.json @@ -0,0 +1,14 @@ +{ + "@metadata": { + "authors": [ + "Meno25", + "روخو" + ] + }, + "mwe-timedtext-back-btn": "رجوع", + "mwe-timedtext-layout-off": "إخفاء الترجمات", + "mwe-timedtext-loading-text": "جاري تحميل النص...", + "mwe-timedtext-textcat-cc": "نصوص توضيحية", + "mwe-timedtext-textcat-cue": "نقاط تلميح", + "mwe-timedtext-upload-timed-text": "إضافة الترجمات" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ast.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ast.json new file mode 100644 index 00000000..9df51f24 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ast.json @@ -0,0 +1,26 @@ +{ + "@metadata": { + "authors": [ + "Xuacu" + ] + }, + "mwe-timedtext-back-btn": "Anterior", + "mwe-timedtext-layout-off": "Tapecer subtítulos", + "mwe-timedtext-loading-text": "Cargando'l testu...", + "mwe-timedtext-textcat-cc": "Lleendes", + "mwe-timedtext-textcat-sub": "Subtítulos", + "mwe-timedtext-textcat-tad": "Descripción del soníu", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-tik": "Testu en movimientu", + "mwe-timedtext-textcat-ar": "Rexones actives", + "mwe-timedtext-textcat-nb": "Anotación", + "mwe-timedtext-textcat-meta": "Metadatos cronometraos", + "mwe-timedtext-textcat-trx": "Trescripción", + "mwe-timedtext-textcat-lrc": "Lletra", + "mwe-timedtext-textcat-lin": "Formatu llingüísticu", + "mwe-timedtext-textcat-cue": "Puntos de referencia", + "mwe-timedtext-no-subs": "Nun hai pistes de testu disponibles", + "mwe-timedtext-language-subtitles-for-clip": "Subtítulos en $1 pal videu: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Nun s'alcontraron los subtítulos en $1 pal videu: $2", + "mwe-timedtext-upload-timed-text": "Añadir subtítulos" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/be-tarask.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/be-tarask.json new file mode 100644 index 00000000..5c25527d --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/be-tarask.json @@ -0,0 +1,28 @@ +{ + "@metadata": { + "authors": [ + "EugeneZelenko", + "Jim-by", + "Wizardist" + ] + }, + "mwe-timedtext-back-btn": "Вярнуцца", + "mwe-timedtext-layout-off": "Схаваць субтытры", + "mwe-timedtext-loading-text": "Загрузка тэксту…", + "mwe-timedtext-textcat-cc": "Субтытры", + "mwe-timedtext-textcat-sub": "Субтытры:", + "mwe-timedtext-textcat-tad": "Аўдыя-апісаньне", + "mwe-timedtext-textcat-ktv": "Караоке", + "mwe-timedtext-textcat-tik": "Тэкставыя карткі", + "mwe-timedtext-textcat-ar": "Актыўныя рэгіёны", + "mwe-timedtext-textcat-nb": "Анатацыя", + "mwe-timedtext-textcat-meta": "Сынхранізаваныя мета-зьвесткі", + "mwe-timedtext-textcat-trx": "Стэнаграма", + "mwe-timedtext-textcat-lrc": "Словы", + "mwe-timedtext-textcat-lin": "Лінгвістычная разьметка", + "mwe-timedtext-textcat-cue": "Сыгнальныя кропкі", + "mwe-timedtext-no-subs": "Субтытраў няма", + "mwe-timedtext-language-subtitles-for-clip": "$1 субтытры для кліпу: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Субтытры $1 для кліпу ня знойдзеныя: $2", + "mwe-timedtext-upload-timed-text": "Дадаць субтытры" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/bg.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/bg.json new file mode 100644 index 00000000..b88de95d --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/bg.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "පසිඳු කාවින්ද" + ] + }, + "mwe-timedtext-back-btn": "Назад" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/bn.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/bn.json new file mode 100644 index 00000000..395fbe7b --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/bn.json @@ -0,0 +1,15 @@ +{ + "@metadata": { + "authors": [ + "Aftab1995", + "Bellayet" + ] + }, + "mwe-timedtext-back-btn": "পিছনে", + "mwe-timedtext-layout-off": "উপশিরোনাম লুকাও", + "mwe-timedtext-loading-text": "টেক্সট লোড হচ্ছে ...", + "mwe-timedtext-textcat-cc": "পরিচয়লিপি", + "mwe-timedtext-textcat-sub": "উপশিরোনাম", + "mwe-timedtext-textcat-tad": "অডিও বিবরণ", + "mwe-timedtext-upload-timed-text": "উপশিরোনাম যুক্ত করুন" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/br.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/br.json new file mode 100644 index 00000000..eacd0f20 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/br.json @@ -0,0 +1,26 @@ +{ + "@metadata": { + "authors": [ + "Fulup", + "Y-M D" + ] + }, + "mwe-timedtext-back-btn": "Distreiñ", + "mwe-timedtext-layout-off": "Kuzhat an istitloù", + "mwe-timedtext-loading-text": "O kargañ an destenn...", + "mwe-timedtext-textcat-cc": "Alc'hwezioù", + "mwe-timedtext-textcat-sub": "Istitloù", + "mwe-timedtext-textcat-tad": "Deskrivadur son", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-tik": "Barenn titouroù", + "mwe-timedtext-textcat-ar": "Rannvroioù oberiant", + "mwe-timedtext-textcat-nb": "Notennadur", + "mwe-timedtext-textcat-meta": "Metaroadennoù sinkronelaet", + "mwe-timedtext-textcat-trx": "Treuzskrivañ", + "mwe-timedtext-textcat-lrc": "Komzoù", + "mwe-timedtext-textcat-lin": "Balizennoù yezhel", + "mwe-timedtext-textcat-cue": "Poent lec'hiañ", + "mwe-timedtext-language-subtitles-for-clip": "$1 istitl evit ar c'hlip : $2", + "mwe-timedtext-language-no-subtitles-for-clip": "N'eo ket bet kavet $1 istitl evit ar c'hlip : $2", + "mwe-timedtext-upload-timed-text": "Enporzhiañ istitloù" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/bs.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/bs.json new file mode 100644 index 00000000..f8d0cd23 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/bs.json @@ -0,0 +1,10 @@ +{ + "@metadata": { + "authors": [ + "CERminator" + ] + }, + "mwe-timedtext-back-btn": "Nazad", + "mwe-timedtext-textcat-sub": "Podnaslovi", + "mwe-timedtext-textcat-tad": "Opis zvuka" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ca.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ca.json new file mode 100644 index 00000000..ce45bfb5 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ca.json @@ -0,0 +1,9 @@ +{ + "@metadata": { + "authors": [ + "Pitort" + ] + }, + "mwe-timedtext-back-btn": "Enrere", + "mwe-timedtext-textcat-sub": "Subtítols" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ce.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ce.json new file mode 100644 index 00000000..f1580f0d --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ce.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Умар" + ] + }, + "mwe-timedtext-textcat-tad": "Аудио-хаам" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/cs.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/cs.json new file mode 100644 index 00000000..94a5e7eb --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/cs.json @@ -0,0 +1,16 @@ +{ + "@metadata": { + "authors": [ + "Mormegil", + "Vks" + ] + }, + "mwe-timedtext-back-btn": "Zpět", + "mwe-timedtext-layout-off": "Skrýt titulky", + "mwe-timedtext-loading-text": "Načítá se text…", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-nb": "Anotace", + "mwe-timedtext-textcat-trx": "Přepis", + "mwe-timedtext-language-subtitles-for-clip": "Titulky ke klipu $2 v jazyce $1", + "mwe-timedtext-language-no-subtitles-for-clip": "Ke klipu $2 nebyly nalezeny titulky v jazyce $1" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/cy.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/cy.json new file mode 100644 index 00000000..fd0eea45 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/cy.json @@ -0,0 +1,26 @@ +{ + "@metadata": { + "authors": [ + "Lloffiwr", + "Robin Owain" + ] + }, + "mwe-timedtext-back-btn": "Yn ôl", + "mwe-timedtext-layout-off": "Cuddio'r isdeitlau", + "mwe-timedtext-loading-text": "Yn llwytho'r testun...", + "mwe-timedtext-textcat-cc": "Geiriad", + "mwe-timedtext-textcat-sub": "Isdeitlau", + "mwe-timedtext-textcat-tad": "Disgrifiad o'r sain", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-tik": "Testun", + "mwe-timedtext-textcat-ar": "Ardaloedd gweithredolo", + "mwe-timedtext-textcat-nb": "Anodiad", + "mwe-timedtext-textcat-meta": "Metadata a amserwyd", + "mwe-timedtext-textcat-trx": "Trawsysgrif", + "mwe-timedtext-textcat-lrc": "Geiriau", + "mwe-timedtext-textcat-cue": "Cerrig milltir", + "mwe-timedtext-no-subs": "Dim traciau testun ar gael", + "mwe-timedtext-language-subtitles-for-clip": "$1 isdeitl ar gael ar gyfer clip: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Dim $1 isdeitl ar gael ar gyfer: $2", + "mwe-timedtext-upload-timed-text": "Ychwanegu isdeitlau" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/de-formal.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/de-formal.json new file mode 100644 index 00000000..10c9c650 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/de-formal.json @@ -0,0 +1,7 @@ +{ + "@metadata": { + "authors": [ + "Kghbln" + ] + } +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/de.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/de.json new file mode 100644 index 00000000..35d1cef9 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/de.json @@ -0,0 +1,28 @@ +{ + "@metadata": { + "authors": [ + "Kghbln", + "Metalhead64", + "Purodha" + ] + }, + "mwe-timedtext-back-btn": "Zurück", + "mwe-timedtext-layout-off": "Untertitel ausblenden", + "mwe-timedtext-loading-text": "Text wird geladen …", + "mwe-timedtext-textcat-cc": "Legenden", + "mwe-timedtext-textcat-sub": "Untertitel", + "mwe-timedtext-textcat-tad": "Beschreibung (Audio)", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-tik": "Text-Ticker", + "mwe-timedtext-textcat-ar": "Aktive Regionen", + "mwe-timedtext-textcat-nb": "Annotation", + "mwe-timedtext-textcat-meta": "„Timed Text“-Metadaten", + "mwe-timedtext-textcat-trx": "Abschrift", + "mwe-timedtext-textcat-lrc": "Liedtext", + "mwe-timedtext-textcat-lin": "Sprachliche Beschreibung", + "mwe-timedtext-textcat-cue": "Cue-Punkte", + "mwe-timedtext-no-subs": "Es sind keine Untertitel verfügbar", + "mwe-timedtext-language-subtitles-for-clip": "Untertitel auf $1 für den Videoclip: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Keine Untertitel auf $1 für den Videoclip gefunden: $2", + "mwe-timedtext-upload-timed-text": "Untertitel hinzufügen" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/diq.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/diq.json new file mode 100644 index 00000000..ee86ed2c --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/diq.json @@ -0,0 +1,13 @@ +{ + "@metadata": { + "authors": [ + "Erdemaslancan", + "Mirzali" + ] + }, + "mwe-timedtext-back-btn": "Peyser", + "mwe-timedtext-textcat-cc": "Bınnuşte", + "mwe-timedtext-textcat-sub": "Sernuştey bıni", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-nb": "Ole şınasiye" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/dsb.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/dsb.json new file mode 100644 index 00000000..362d95c8 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/dsb.json @@ -0,0 +1,27 @@ +{ + "@metadata": { + "authors": [ + "Derbeth", + "Michawiki" + ] + }, + "mwe-timedtext-back-btn": "Slědk", + "mwe-timedtext-layout-off": "Pódtitele schowaś", + "mwe-timedtext-loading-text": "Tekst se zacytujo...", + "mwe-timedtext-textcat-cc": "Wopisanja", + "mwe-timedtext-textcat-sub": "Pódtitele", + "mwe-timedtext-textcat-tad": "Awdiowopisanje", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-tik": "Běžecy tekst", + "mwe-timedtext-textcat-ar": "Aktiwne regiony", + "mwe-timedtext-textcat-nb": "Anotacija", + "mwe-timedtext-textcat-meta": "Synchronizěrowane metadaty", + "mwe-timedtext-textcat-trx": "Pśepisaś", + "mwe-timedtext-textcat-lrc": "Spiwny tekst", + "mwe-timedtext-textcat-lin": "Rěcywědne wopisanje", + "mwe-timedtext-textcat-cue": "Zastupne dypki", + "mwe-timedtext-no-subs": "Žedne pódtitele k dispoziciji", + "mwe-timedtext-language-subtitles-for-clip": "$1 {{PLURAL:$1|pódtitel|pódtitela|pódtitele|oódtitelow}} za klip: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Žedne pódtitele $1 su se za klip namakali: $2", + "mwe-timedtext-upload-timed-text": "Pódtitele pśidaś" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/el.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/el.json new file mode 100644 index 00000000..9de04eff --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/el.json @@ -0,0 +1,24 @@ +{ + "@metadata": { + "authors": [ + "Geraki" + ] + }, + "mwe-timedtext-back-btn": "Επιστροφή", + "mwe-timedtext-layout-off": "Απόκρυψη υπότιτλων", + "mwe-timedtext-loading-text": "Φόρτωση κείμενου...", + "mwe-timedtext-textcat-cc": "Λεζάντες", + "mwe-timedtext-textcat-sub": "Υπότιτλοι", + "mwe-timedtext-textcat-tad": "Ακουστική περιγραφή", + "mwe-timedtext-textcat-ktv": "Καραόκε", + "mwe-timedtext-textcat-tik": "Κυλιόμενο κείμενο", + "mwe-timedtext-textcat-ar": "Ενεργές περιοχές", + "mwe-timedtext-textcat-nb": "Σχόλιο", + "mwe-timedtext-textcat-meta": "Χρονισμένα μεταδεδομένα", + "mwe-timedtext-textcat-trx": "Μεταγραφή", + "mwe-timedtext-textcat-lrc": "Στίχοι", + "mwe-timedtext-textcat-lin": "Γλωσσολογική σύνταξη", + "mwe-timedtext-textcat-cue": "Cue points", + "mwe-timedtext-language-subtitles-for-clip": "$1 υπότιτλοι για το βίντεο: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Δεν βρέθηκαν υπότιτλοι $1 για το βίντεο: $2" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/en.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/en.json new file mode 100644 index 00000000..0505d5b7 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/en.json @@ -0,0 +1,25 @@ +{ + "@metadata": { + "authors": [] + }, + "mwe-timedtext-back-btn": "Back", + "mwe-timedtext-layout-off": "Hide subtitles", + "mwe-timedtext-loading-text": "Loading text ...", + "mwe-timedtext-key-language": "$1, $2", + "mwe-timedtext-textcat-cc": "Captions", + "mwe-timedtext-textcat-sub": "Subtitles", + "mwe-timedtext-textcat-tad": "Audio description", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-tik": "Ticker text", + "mwe-timedtext-textcat-ar": "Active regions", + "mwe-timedtext-textcat-nb": "Annotation", + "mwe-timedtext-textcat-meta": "Timed metadata", + "mwe-timedtext-textcat-trx": "Transcript", + "mwe-timedtext-textcat-lrc": "Lyrics", + "mwe-timedtext-textcat-lin": "Linguistic markup", + "mwe-timedtext-textcat-cue": "Cue points", + "mwe-timedtext-no-subs": "No text tracks available", + "mwe-timedtext-language-subtitles-for-clip": "$1 subtitles for clip: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "No $1 subtitles were found for clip: $2", + "mwe-timedtext-upload-timed-text": "Add subtitles" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/eo.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/eo.json new file mode 100644 index 00000000..f787b8a6 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/eo.json @@ -0,0 +1,7 @@ +{ + "@metadata": { + "authors": [ + "Yekrats" + ] + } +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/es.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/es.json new file mode 100644 index 00000000..e753ece1 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/es.json @@ -0,0 +1,30 @@ +{ + "@metadata": { + "authors": [ + "Armando-Martin", + "Crazymadlover", + "Locos epraix", + "Pertile", + "Translationista" + ] + }, + "mwe-timedtext-back-btn": "Atrás", + "mwe-timedtext-layout-off": "Ocultar subtítulos", + "mwe-timedtext-loading-text": "Cargando texto ...", + "mwe-timedtext-textcat-cc": "Leyendas", + "mwe-timedtext-textcat-sub": "Subtítulos", + "mwe-timedtext-textcat-tad": "Descripción de audio", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-tik": "Texto desplazable", + "mwe-timedtext-textcat-ar": "Regiones activas", + "mwe-timedtext-textcat-nb": "Anotación", + "mwe-timedtext-textcat-meta": "Metadatos sincronizados", + "mwe-timedtext-textcat-trx": "Transcribir", + "mwe-timedtext-textcat-lrc": "Letra", + "mwe-timedtext-textcat-lin": "Marcador lingüístico", + "mwe-timedtext-textcat-cue": "Puntos de referencia", + "mwe-timedtext-no-subs": "No hay pistas de texto disponibles", + "mwe-timedtext-language-subtitles-for-clip": "$1 subtítulos para el clip: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "No se ha encontrado subtítulos $1 para el clip: $2", + "mwe-timedtext-upload-timed-text": "Añadir subtítulos" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/et.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/et.json new file mode 100644 index 00000000..a57273aa --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/et.json @@ -0,0 +1,18 @@ +{ + "@metadata": { + "authors": [ + "Avjoska", + "Pikne" + ] + }, + "mwe-timedtext-layout-off": "Peida alltiitrid", + "mwe-timedtext-loading-text": "Teksti laadimine...", + "mwe-timedtext-textcat-sub": "Alltiitrid", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-meta": "Ajastatud metaandmed", + "mwe-timedtext-textcat-lrc": "Laulusõnad", + "mwe-timedtext-no-subs": "Alltiitreid pole saadaval", + "mwe-timedtext-language-subtitles-for-clip": "Lõigu $2 $1 alltiitrid", + "mwe-timedtext-language-no-subtitles-for-clip": "Lõigu $2 jaoks ei leitud $1 alltiitreid", + "mwe-timedtext-upload-timed-text": "Lisa alltiitrid" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/eu.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/eu.json new file mode 100644 index 00000000..5c30fe9d --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/eu.json @@ -0,0 +1,10 @@ +{ + "@metadata": { + "authors": [ + "පසිඳු කාවින්ද", + "Subi" + ] + }, + "mwe-timedtext-back-btn": "Atzera", + "mwe-timedtext-textcat-ktv": "Karaokea" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fa.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fa.json new file mode 100644 index 00000000..c6fa166e --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fa.json @@ -0,0 +1,30 @@ +{ + "@metadata": { + "authors": [ + "Armin1392", + "Ebraminio", + "Pouyana", + "Reza1615", + "پاناروما" + ] + }, + "mwe-timedtext-back-btn": "بازگشت", + "mwe-timedtext-layout-off": "پنهان کردن زیرنویس", + "mwe-timedtext-loading-text": "در حال بارگیری متن ...", + "mwe-timedtext-textcat-cc": "عناوین:", + "mwe-timedtext-textcat-sub": "زیرنویس", + "mwe-timedtext-textcat-tad": "توضیح صوتی", + "mwe-timedtext-textcat-ktv": "کارائوکه", + "mwe-timedtext-textcat-tik": "متن تیکر", + "mwe-timedtext-textcat-ar": "مناطق فعال", + "mwe-timedtext-textcat-nb": "یادداشت", + "mwe-timedtext-textcat-meta": "فرادادهٔ به هنگام", + "mwe-timedtext-textcat-trx": "رونوشت", + "mwe-timedtext-textcat-lrc": "متن ترانهها", + "mwe-timedtext-textcat-lin": "زبان نشانهگذاری", + "mwe-timedtext-textcat-cue": "نقاط نشانه", + "mwe-timedtext-no-subs": "هیچ آهنگ متنی دردسترس نیست", + "mwe-timedtext-language-subtitles-for-clip": "$1 زیرنویس برای کلیپ: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "هیچ $1 زیرنویسی برای کلیپ پیدا نشد: $2", + "mwe-timedtext-upload-timed-text": "اضافه کردن زیرنویس" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fi.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fi.json new file mode 100644 index 00000000..e0fa5944 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fi.json @@ -0,0 +1,16 @@ +{ + "@metadata": { + "authors": [ + "Nedergard", + "Nike", + "Silvonen" + ] + }, + "mwe-timedtext-back-btn": "Takaisin", + "mwe-timedtext-layout-off": "Piilota tekstitys", + "mwe-timedtext-loading-text": "Ladataan tekstiä...", + "mwe-timedtext-textcat-cc": "Kuvatekstit", + "mwe-timedtext-textcat-sub": "Tekstitykset", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-upload-timed-text": "Lisää tekstitys" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fr.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fr.json new file mode 100644 index 00000000..4e74e546 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fr.json @@ -0,0 +1,29 @@ +{ + "@metadata": { + "authors": [ + "IAlex", + "Peter17", + "Tititou36", + "Verdy p" + ] + }, + "mwe-timedtext-back-btn": "Arrière", + "mwe-timedtext-layout-off": "Masquer les sous-titres", + "mwe-timedtext-loading-text": "Chargement du texte ...", + "mwe-timedtext-textcat-cc": "Légendes", + "mwe-timedtext-textcat-sub": "Sous-titres", + "mwe-timedtext-textcat-tad": "Description audio", + "mwe-timedtext-textcat-ktv": "Karaoké", + "mwe-timedtext-textcat-tik": "Barre d'informations", + "mwe-timedtext-textcat-ar": "Régions actives", + "mwe-timedtext-textcat-nb": "Annotation", + "mwe-timedtext-textcat-meta": "métadonnées synchronisées", + "mwe-timedtext-textcat-trx": "Transcription", + "mwe-timedtext-textcat-lrc": "Paroles", + "mwe-timedtext-textcat-lin": "Balisage linguistique", + "mwe-timedtext-textcat-cue": "Points de repère", + "mwe-timedtext-no-subs": "Aucun texte de piste disponible", + "mwe-timedtext-language-subtitles-for-clip": "$1 sous-titres pour clip : $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Aucun sous-titre $1 n'a été trouvé pour le clip : $2", + "mwe-timedtext-upload-timed-text": "Ajouter des sous-titres" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/frp.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/frp.json new file mode 100644 index 00000000..eeb629b9 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/frp.json @@ -0,0 +1,26 @@ +{ + "@metadata": { + "authors": [ + "ChrisPtDe" + ] + }, + "mwe-timedtext-back-btn": "Tornar", + "mwe-timedtext-layout-off": "Cachiér los sot-titros", + "mwe-timedtext-loading-text": "Chargement du tèxto ...", + "mwe-timedtext-textcat-cc": "Lègendes", + "mwe-timedtext-textcat-sub": "Sot-titros", + "mwe-timedtext-textcat-tad": "Dèscripcion ôdiô", + "mwe-timedtext-textcat-ktv": "Caraoquè", + "mwe-timedtext-textcat-tik": "Bârra d’enformacions", + "mwe-timedtext-textcat-ar": "Règ·ions actives", + "mwe-timedtext-textcat-nb": "Nota", + "mwe-timedtext-textcat-meta": "Mètabalyês sincronisâs", + "mwe-timedtext-textcat-trx": "Transcripcion", + "mwe-timedtext-textcat-lrc": "Paroles", + "mwe-timedtext-textcat-lin": "Balisâjo lengouistico", + "mwe-timedtext-textcat-cue": "Pouents de repèro", + "mwe-timedtext-no-subs": "Gins de pista de tèxto disponibla", + "mwe-timedtext-language-subtitles-for-clip": "$1 sot-titros por clipe : $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Nion sot-titro $1 at étâ trovâ por lo clipe : $2", + "mwe-timedtext-upload-timed-text": "Apondre des sot-titros" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fy.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fy.json new file mode 100644 index 00000000..69f89218 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/fy.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Robin0van0der0vliet" + ] + }, + "mwe-timedtext-back-btn": "Foarige" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/gl.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/gl.json new file mode 100644 index 00000000..df9d0409 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/gl.json @@ -0,0 +1,26 @@ +{ + "@metadata": { + "authors": [ + "Toliño" + ] + }, + "mwe-timedtext-back-btn": "Volver", + "mwe-timedtext-layout-off": "Agochar os subtítulos", + "mwe-timedtext-loading-text": "Cargando o texto...", + "mwe-timedtext-textcat-cc": "Pés de foto", + "mwe-timedtext-textcat-sub": "Subtítulos", + "mwe-timedtext-textcat-tad": "Descrición do son", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-tik": "Barra de información", + "mwe-timedtext-textcat-ar": "Rexións activas", + "mwe-timedtext-textcat-nb": "Anotación", + "mwe-timedtext-textcat-meta": "Metadatos sincronizados", + "mwe-timedtext-textcat-trx": "Transcrición", + "mwe-timedtext-textcat-lrc": "Letra", + "mwe-timedtext-textcat-lin": "Formato lingüístico", + "mwe-timedtext-textcat-cue": "Puntos de sinal", + "mwe-timedtext-no-subs": "Non hai pistas de texto dispoñibles", + "mwe-timedtext-language-subtitles-for-clip": "Subtítulos en $1 para o vídeo: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Non se atoparon os subtítulos en $1 para o vídeo: $2", + "mwe-timedtext-upload-timed-text": "Engadir subtítulos" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/gsw.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/gsw.json new file mode 100644 index 00000000..c48c3c0c --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/gsw.json @@ -0,0 +1,27 @@ +{ + "@metadata": { + "authors": [ + "Als-Chlämens", + "Als-Holder" + ] + }, + "mwe-timedtext-back-btn": "Zruck", + "mwe-timedtext-layout-off": "Untertitel uusblände", + "mwe-timedtext-loading-text": "Am Lade vum Text ...", + "mwe-timedtext-textcat-cc": "Bschryybige", + "mwe-timedtext-textcat-sub": "Untertitel", + "mwe-timedtext-textcat-tad": "Audio-Bschryybig", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-tik": "Text-Ticker", + "mwe-timedtext-textcat-ar": "Aktivi Regione", + "mwe-timedtext-textcat-nb": "Aamerkig", + "mwe-timedtext-textcat-meta": "Ächtzyt-Metadate", + "mwe-timedtext-textcat-trx": "Abschrift", + "mwe-timedtext-textcat-lrc": "Liedtext", + "mwe-timedtext-textcat-lin": "Sprochwisseschaftligi Bschryybig", + "mwe-timedtext-textcat-cue": "Cue-Pinkt", + "mwe-timedtext-no-subs": "Untertitel sin nit verfiegbar", + "mwe-timedtext-language-subtitles-for-clip": "$1 Untertitel gfunde fir dr Videoclip: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Kei $1 Untertitel gfunde fir dr Videoclip: $2", + "mwe-timedtext-upload-timed-text": "Untertitel uffelade" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/he.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/he.json new file mode 100644 index 00000000..5137aa27 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/he.json @@ -0,0 +1,28 @@ +{ + "@metadata": { + "authors": [ + "Amire80", + "Guycn2", + "YaronSh" + ] + }, + "mwe-timedtext-back-btn": "חזרה", + "mwe-timedtext-layout-off": "הסתרת כתוביות", + "mwe-timedtext-loading-text": "טעינת טקסט...", + "mwe-timedtext-textcat-cc": "כותרות", + "mwe-timedtext-textcat-sub": "כתוביות", + "mwe-timedtext-textcat-tad": "תיאור השמע", + "mwe-timedtext-textcat-ktv": "קראוקה", + "mwe-timedtext-textcat-tik": "שפת השורה הרצה", + "mwe-timedtext-textcat-ar": "אזורים פעילים", + "mwe-timedtext-textcat-nb": "פרשנות", + "mwe-timedtext-textcat-meta": "מטא־מתונים מתוזמנים", + "mwe-timedtext-textcat-trx": "תמליל", + "mwe-timedtext-textcat-lrc": "מילות השיר", + "mwe-timedtext-textcat-lin": "סימון בלשני", + "mwe-timedtext-textcat-cue": "נקודות סימנית", + "mwe-timedtext-no-subs": "אין רצועת תמליל זמינה", + "mwe-timedtext-language-subtitles-for-clip": "כתוביות ב{{grammar:תחילית|$1}} עבור הסרטון $2", + "mwe-timedtext-language-no-subtitles-for-clip": "לא נמצאו כתוביות ב{{grammar:תחילית|$1}} עבור $2", + "mwe-timedtext-upload-timed-text": "הוספת כתוביות" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/hsb.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/hsb.json new file mode 100644 index 00000000..325044d8 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/hsb.json @@ -0,0 +1,26 @@ +{ + "@metadata": { + "authors": [ + "Michawiki" + ] + }, + "mwe-timedtext-back-btn": "Wróćo", + "mwe-timedtext-layout-off": "Podtitule schować", + "mwe-timedtext-loading-text": "Tekst so začituje...", + "mwe-timedtext-textcat-cc": "Nadpisma", + "mwe-timedtext-textcat-sub": "Podtitule", + "mwe-timedtext-textcat-tad": "Awdiowopisanje", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-tik": "Tekstowy běžacy pask", + "mwe-timedtext-textcat-ar": "Aktiwne regiony", + "mwe-timedtext-textcat-nb": "Anotacija", + "mwe-timedtext-textcat-meta": "Synchronizowane metadaty", + "mwe-timedtext-textcat-trx": "Přepis", + "mwe-timedtext-textcat-lrc": "Spěwowy tekst", + "mwe-timedtext-textcat-lin": "Rěčespytne wopisanje", + "mwe-timedtext-textcat-cue": "Zastupne dypki", + "mwe-timedtext-no-subs": "Žane podtitule k dispoziciji", + "mwe-timedtext-language-subtitles-for-clip": "$1 {{PLURAL:$1|podtitul|podtitulej|podtitule|podtitulow}} za klip: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Žane podtitule $1 za klip namakane: $2", + "mwe-timedtext-upload-timed-text": "Podtitule přidać" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/hu.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/hu.json new file mode 100644 index 00000000..a5eb9692 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/hu.json @@ -0,0 +1,23 @@ +{ + "@metadata": { + "authors": [ + "Dani", + "Glanthor Reviol", + "Misibacsi" + ] + }, + "mwe-timedtext-back-btn": "Vissza", + "mwe-timedtext-layout-off": "Feliratok elrejtése", + "mwe-timedtext-loading-text": "Szöveg betöltése…", + "mwe-timedtext-textcat-cc": "Feliratok", + "mwe-timedtext-textcat-sub": "Felirat", + "mwe-timedtext-textcat-tad": "Hang leírása", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-ar": "Aktív régiók", + "mwe-timedtext-textcat-nb": "Annotáció", + "mwe-timedtext-textcat-meta": "Időzített metaadatok", + "mwe-timedtext-textcat-trx": "Átirat", + "mwe-timedtext-textcat-lrc": "Dalszöveg", + "mwe-timedtext-textcat-lin": "Nyelvi jelölés", + "mwe-timedtext-upload-timed-text": "Felirat hozzáadása" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ia.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ia.json new file mode 100644 index 00000000..624dc45d --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ia.json @@ -0,0 +1,26 @@ +{ + "@metadata": { + "authors": [ + "McDutchie" + ] + }, + "mwe-timedtext-back-btn": "Retornar", + "mwe-timedtext-layout-off": "Celar subtitulos", + "mwe-timedtext-loading-text": "Carga texto…", + "mwe-timedtext-textcat-cc": "Subtitulos", + "mwe-timedtext-textcat-sub": "Subtitulos", + "mwe-timedtext-textcat-tad": "Description audio", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-tik": "Barra de information", + "mwe-timedtext-textcat-ar": "Regiones active", + "mwe-timedtext-textcat-nb": "Annotation", + "mwe-timedtext-textcat-meta": "Metadatos de synchronisation", + "mwe-timedtext-textcat-trx": "Transcription", + "mwe-timedtext-textcat-lrc": "Lyricos", + "mwe-timedtext-textcat-lin": "Marcation lingusitic", + "mwe-timedtext-textcat-cue": "Punctos de entrata", + "mwe-timedtext-no-subs": "Subtitulos non disponibile", + "mwe-timedtext-language-subtitles-for-clip": "Subtitulos in $1 pro le clip: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Nulle subtitulos in $1 ha essite trovate pro le clip: $2", + "mwe-timedtext-upload-timed-text": "Adder subtitulos" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/id.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/id.json new file mode 100644 index 00000000..12a35bd7 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/id.json @@ -0,0 +1,27 @@ +{ + "@metadata": { + "authors": [ + "Farras", + "IvanLanin" + ] + }, + "mwe-timedtext-back-btn": "Kembali", + "mwe-timedtext-layout-off": "Sembunyikan subjudul", + "mwe-timedtext-loading-text": "Memuat teks ...", + "mwe-timedtext-textcat-cc": "Keterangan", + "mwe-timedtext-textcat-sub": "Subjudul", + "mwe-timedtext-textcat-tad": "Deskripsi audio", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-tik": "Teks tik", + "mwe-timedtext-textcat-ar": "Wilayah aktif", + "mwe-timedtext-textcat-nb": "Anotasi", + "mwe-timedtext-textcat-meta": "Data meta berjangka waktu", + "mwe-timedtext-textcat-trx": "Transkrip", + "mwe-timedtext-textcat-lrc": "Lirik", + "mwe-timedtext-textcat-lin": "Ubahan linguistik", + "mwe-timedtext-textcat-cue": "Titik acuan", + "mwe-timedtext-no-subs": "Jalur teks tidak tersedia", + "mwe-timedtext-language-subtitles-for-clip": "Subjudul $1 untuk klip: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Tidak ada subjudul $1 yang ditemukan untuk klip: $2", + "mwe-timedtext-upload-timed-text": "Unggah teks film" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/it.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/it.json new file mode 100644 index 00000000..4e2fad3a --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/it.json @@ -0,0 +1,29 @@ +{ + "@metadata": { + "authors": [ + "Beta16", + "Darth Kule", + "F. Cosoleto", + "Gianfranco" + ] + }, + "mwe-timedtext-back-btn": "Indietro", + "mwe-timedtext-layout-off": "Nascondi sottotitoli", + "mwe-timedtext-loading-text": "Caricamento testo...", + "mwe-timedtext-textcat-cc": "Didascalie", + "mwe-timedtext-textcat-sub": "Sottotitoli", + "mwe-timedtext-textcat-tad": "Descrizione audio", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-tik": "Testo in movimento", + "mwe-timedtext-textcat-ar": "Regioni attive", + "mwe-timedtext-textcat-nb": "Annotazione", + "mwe-timedtext-textcat-meta": "Metadati temporizzati", + "mwe-timedtext-textcat-trx": "Trascrizione", + "mwe-timedtext-textcat-lrc": "Testi", + "mwe-timedtext-textcat-lin": "Markup linguistico", + "mwe-timedtext-textcat-cue": "Punti d'entrata", + "mwe-timedtext-no-subs": "Nessuna traccia di testo disponibile", + "mwe-timedtext-language-subtitles-for-clip": "sottotitoli in $1 per il filmato: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Sottotitoli in $1 non trovati per il filmato: $2", + "mwe-timedtext-upload-timed-text": "Aggiungi sottotitoli" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ja.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ja.json new file mode 100644 index 00000000..7e048693 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ja.json @@ -0,0 +1,29 @@ +{ + "@metadata": { + "authors": [ + "Aotake", + "Hosiryuhosi", + "Shirayuki", + "Yanajin66", + "青子守歌" + ] + }, + "mwe-timedtext-back-btn": "戻る", + "mwe-timedtext-layout-off": "字幕を隠す", + "mwe-timedtext-loading-text": "テキストの読み込み中...", + "mwe-timedtext-textcat-cc": "見出し", + "mwe-timedtext-textcat-sub": "字幕", + "mwe-timedtext-textcat-tad": "音声の説明", + "mwe-timedtext-textcat-ktv": "カラオケ", + "mwe-timedtext-textcat-tik": "ティッカー文章", + "mwe-timedtext-textcat-ar": "アクティブな領域", + "mwe-timedtext-textcat-nb": "注釈", + "mwe-timedtext-textcat-meta": "時間メタデータ", + "mwe-timedtext-textcat-trx": "複写", + "mwe-timedtext-textcat-lrc": "歌詞", + "mwe-timedtext-textcat-lin": "言語マーク", + "mwe-timedtext-textcat-cue": "キューポイント", + "mwe-timedtext-language-subtitles-for-clip": "クリップ $2 の$1字幕", + "mwe-timedtext-language-no-subtitles-for-clip": "クリップ $2 には$1字幕がありません", + "mwe-timedtext-upload-timed-text": "字幕を追加" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ka.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ka.json new file mode 100644 index 00000000..05eb95f5 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ka.json @@ -0,0 +1,24 @@ +{ + "@metadata": { + "authors": [ + "David1010" + ] + }, + "mwe-timedtext-back-btn": "უკან", + "mwe-timedtext-layout-off": "სუბტიტრების დამალვა", + "mwe-timedtext-loading-text": "იტვირთება ტექსტი ...", + "mwe-timedtext-textcat-cc": "წარწერები", + "mwe-timedtext-textcat-sub": "სუბტიტრები", + "mwe-timedtext-textcat-tad": "აუდიო აღწერა", + "mwe-timedtext-textcat-ktv": "კარაოკე", + "mwe-timedtext-textcat-tik": "ტექსტური ბარათები", + "mwe-timedtext-textcat-ar": "აქტიური რეგიონები", + "mwe-timedtext-textcat-nb": "ანოტაცია", + "mwe-timedtext-textcat-meta": "სინქრონიზირებული მეტამონაცემები", + "mwe-timedtext-textcat-trx": "სტენოგრამა", + "mwe-timedtext-textcat-lrc": "სიმღერის ტექსტები", + "mwe-timedtext-textcat-lin": "ლინგვისტური დანამატი", + "mwe-timedtext-textcat-cue": "ნიშნული წერტილები", + "mwe-timedtext-language-subtitles-for-clip": "$1 სუბტიტრები კლიპისათვის: $2", + "mwe-timedtext-upload-timed-text": "სუბტიტრების დამატება" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ko.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ko.json new file mode 100644 index 00000000..9b4faaf5 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ko.json @@ -0,0 +1,26 @@ +{ + "@metadata": { + "authors": [ + "아라" + ] + }, + "mwe-timedtext-back-btn": "뒤로", + "mwe-timedtext-layout-off": "자막 숨기기", + "mwe-timedtext-loading-text": "텍스트 불러오는 중 ...", + "mwe-timedtext-textcat-cc": "설명", + "mwe-timedtext-textcat-sub": "자막", + "mwe-timedtext-textcat-tad": "소리 설명", + "mwe-timedtext-textcat-ktv": "가라오케", + "mwe-timedtext-textcat-tik": "표시기 문자", + "mwe-timedtext-textcat-ar": "활성 영역", + "mwe-timedtext-textcat-nb": "주석", + "mwe-timedtext-textcat-meta": "시간 메타데이터", + "mwe-timedtext-textcat-trx": "복사", + "mwe-timedtext-textcat-lrc": "가사", + "mwe-timedtext-textcat-lin": "언어 마크업", + "mwe-timedtext-textcat-cue": "큐 포인트", + "mwe-timedtext-no-subs": "사용할 수 있는 텍스트 트랙이 없습니다", + "mwe-timedtext-language-subtitles-for-clip": "클립에 대한 $1 자막: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "클립에 대한 $1 자막을 찾을 수 없습니다: $2", + "mwe-timedtext-upload-timed-text": "자막 추가" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ksh.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ksh.json new file mode 100644 index 00000000..13036810 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ksh.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Purodha" + ] + }, + "mwe-timedtext-language-no-subtitles-for-clip": "Mer han kei $1 Ongertittelle jefonge för dat Shtöck: $2" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/lb.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/lb.json new file mode 100644 index 00000000..ad8d40e7 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/lb.json @@ -0,0 +1,23 @@ +{ + "@metadata": { + "authors": [ + "Robby", + "Soued031" + ] + }, + "mwe-timedtext-back-btn": "Zréck", + "mwe-timedtext-layout-off": "Ënnertitele verstoppen", + "mwe-timedtext-loading-text": "Text gëtt gelueden ...", + "mwe-timedtext-textcat-sub": "Ënnertitelen", + "mwe-timedtext-textcat-tad": "Audio-Beschreiwung", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-tik": "Text-Ticker", + "mwe-timedtext-textcat-ar": "Aktiv Regiounen", + "mwe-timedtext-textcat-nb": "Notiz", + "mwe-timedtext-textcat-lrc": "Liddertext", + "mwe-timedtext-textcat-lin": "Linguistesch Markéierung", + "mwe-timedtext-textcat-cue": "Referenz-Punkten", + "mwe-timedtext-language-subtitles-for-clip": "$1 Ënnertitele fir de Clip: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Keng $1 Ënnertitele goufe fonnt fir de Clip: $2", + "mwe-timedtext-upload-timed-text": "Ënnertitelen derbäisetzen" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/lt.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/lt.json new file mode 100644 index 00000000..af653701 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/lt.json @@ -0,0 +1,9 @@ +{ + "@metadata": { + "authors": [ + "Hugo.arg" + ] + }, + "mwe-timedtext-no-subs": "Nėra tekstinių takelių", + "mwe-timedtext-upload-timed-text": "Pridėti subtitrus" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/lv.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/lv.json new file mode 100644 index 00000000..55f99f5a --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/lv.json @@ -0,0 +1,9 @@ +{ + "@metadata": { + "authors": [ + "Papuass" + ] + }, + "mwe-timedtext-textcat-nb": "Anotācija", + "mwe-timedtext-textcat-trx": "Transkripts" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/mk.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/mk.json new file mode 100644 index 00000000..1dd29c01 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/mk.json @@ -0,0 +1,26 @@ +{ + "@metadata": { + "authors": [ + "Bjankuloski06" + ] + }, + "mwe-timedtext-back-btn": "Назад", + "mwe-timedtext-layout-off": "Скриј титлови", + "mwe-timedtext-loading-text": "Го вчитувам текстот...", + "mwe-timedtext-textcat-cc": "Опис", + "mwe-timedtext-textcat-sub": "Титлови", + "mwe-timedtext-textcat-tad": "Аудио-опис", + "mwe-timedtext-textcat-ktv": "Караоке", + "mwe-timedtext-textcat-tik": "Текст-картички", + "mwe-timedtext-textcat-ar": "Активни региони", + "mwe-timedtext-textcat-nb": "Прибелешка", + "mwe-timedtext-textcat-meta": "Синхронизирани метаподатоци", + "mwe-timedtext-textcat-trx": "Стенограм", + "mwe-timedtext-textcat-lrc": "Текст на песната", + "mwe-timedtext-textcat-lin": "Лингвистичко означување", + "mwe-timedtext-textcat-cue": "Моментни точки", + "mwe-timedtext-no-subs": "Нема титлови на располагање", + "mwe-timedtext-language-subtitles-for-clip": "$1 — титлови за снимката: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Нема пронајдено титлови на $1 за снимката: $2", + "mwe-timedtext-upload-timed-text": "Стави титлови" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ml.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ml.json new file mode 100644 index 00000000..a8d34824 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ml.json @@ -0,0 +1,26 @@ +{ + "@metadata": { + "authors": [ + "Praveenp" + ] + }, + "mwe-timedtext-back-btn": "പുറകോട്ട്", + "mwe-timedtext-layout-off": "സംഭാഷണരേഖ മറയ്ക്കുക", + "mwe-timedtext-loading-text": "എഴുത്ത് ശേഖരിക്കുന്നു...", + "mwe-timedtext-textcat-cc": "തലവാക്യം", + "mwe-timedtext-textcat-sub": "സംഭാഷണരേഖകൾ", + "mwe-timedtext-textcat-tad": "ശബ്ദത്തിന്റെ വിവരണം", + "mwe-timedtext-textcat-ktv": "കരോക്കേ", + "mwe-timedtext-textcat-tik": "മിന്നിവരുന്ന എഴുത്ത്", + "mwe-timedtext-textcat-ar": "സജീവമായ പ്രദേശങ്ങൾ", + "mwe-timedtext-textcat-nb": "ടിപ്പണി", + "mwe-timedtext-textcat-meta": "സമയമനുസരിച്ചുള്ള മെറ്റാഡേറ്റ", + "mwe-timedtext-textcat-trx": "പകർത്തിയെഴുത്ത്", + "mwe-timedtext-textcat-lrc": "വരികൾ", + "mwe-timedtext-textcat-lin": "ഭാഷാസംബന്ധിയായ അടയാളഭാഷ", + "mwe-timedtext-textcat-cue": "സൂചക ബിന്ദുക്കൾ", + "mwe-timedtext-no-subs": "എഴുത്തുകളുടെ വരി ലഭ്യമല്ല", + "mwe-timedtext-language-subtitles-for-clip": "ഈ മീഡിയശകലത്തിന് $1 ഭാഷയിലുള്ള സംഭാഷണരേഖ: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "ഈ മീഡിയശകലത്തിന് $1 ഭാഷയിലുള്ള സംഭാഷണരേഖയൊന്നും കണ്ടെത്താനായില്ല: $2", + "mwe-timedtext-upload-timed-text": "സംഭാഷണരേഖ കൂട്ടിച്ചേർക്കുക" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ms.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ms.json new file mode 100644 index 00000000..712fff27 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ms.json @@ -0,0 +1,26 @@ +{ + "@metadata": { + "authors": [ + "Anakmalaysia" + ] + }, + "mwe-timedtext-back-btn": "Kembali", + "mwe-timedtext-layout-off": "Sorokkan sari kata", + "mwe-timedtext-loading-text": "Teks sedang dimuatkan...", + "mwe-timedtext-textcat-cc": "Kapsyen", + "mwe-timedtext-textcat-sub": "Sari kata", + "mwe-timedtext-textcat-tad": "Keterangan audio", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-tik": "Teks ticker", + "mwe-timedtext-textcat-ar": "Kawasan aktif", + "mwe-timedtext-textcat-nb": "Anotasi", + "mwe-timedtext-textcat-meta": "Metadata bermasa", + "mwe-timedtext-textcat-trx": "Transkrip", + "mwe-timedtext-textcat-lrc": "Lirik", + "mwe-timedtext-textcat-lin": "Penanda linguistik", + "mwe-timedtext-textcat-cue": "Titik kiu", + "mwe-timedtext-no-subs": "Tidak terdapat runut teks", + "mwe-timedtext-language-subtitles-for-clip": "Sari kata $1 untuk klip: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Tidak terdapat sari kata $1 untuk klip: $2", + "mwe-timedtext-upload-timed-text": "Letak sari kata" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/nb.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/nb.json new file mode 100644 index 00000000..a273d46b --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/nb.json @@ -0,0 +1,25 @@ +{ + "@metadata": { + "authors": [ + "Danmichaelo", + "Nghtwlkr" + ] + }, + "mwe-timedtext-back-btn": "Tilbake", + "mwe-timedtext-layout-off": "Gjem undertekster", + "mwe-timedtext-loading-text": "Laster tekst ...", + "mwe-timedtext-textcat-cc": "Undertektster", + "mwe-timedtext-textcat-sub": "Undertekster", + "mwe-timedtext-textcat-tad": "Lydbeskrivelse", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-tik": "Tekst-ticker", + "mwe-timedtext-textcat-ar": "Aktive regioner", + "mwe-timedtext-textcat-nb": "Merknad", + "mwe-timedtext-textcat-meta": "Tidsbestemt metadata", + "mwe-timedtext-textcat-trx": "Transkripsjon", + "mwe-timedtext-textcat-lrc": "Tekster", + "mwe-timedtext-no-subs": "Ingen tekstspor finnes", + "mwe-timedtext-language-subtitles-for-clip": "Undertekster på $1 for klippet: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Ingen undertekster på $1 ble funnet for klippet: $2", + "mwe-timedtext-upload-timed-text": "Legg til undertekster" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/nl.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/nl.json new file mode 100644 index 00000000..7b225402 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/nl.json @@ -0,0 +1,26 @@ +{ + "@metadata": { + "authors": [ + "Siebrand" + ] + }, + "mwe-timedtext-back-btn": "Terug", + "mwe-timedtext-layout-off": "Ondertitels verbergen", + "mwe-timedtext-loading-text": "Bezig met het laden van de tekst...", + "mwe-timedtext-textcat-cc": "Ondertitels", + "mwe-timedtext-textcat-sub": "Ondertitels", + "mwe-timedtext-textcat-tad": "Audiobeschrijving", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-tik": "Informatiebalk", + "mwe-timedtext-textcat-ar": "Actieve gebieden", + "mwe-timedtext-textcat-nb": "Annotatie", + "mwe-timedtext-textcat-meta": "Tijdgebaseerde metadata", + "mwe-timedtext-textcat-trx": "Transcriptie", + "mwe-timedtext-textcat-lrc": "Songteksten", + "mwe-timedtext-textcat-lin": "Taalkundige markup", + "mwe-timedtext-textcat-cue": "Richtpunten", + "mwe-timedtext-no-subs": "Er zijn geen teksttracks beschikbaar", + "mwe-timedtext-language-subtitles-for-clip": "Ondertitels in het $1 voor clip: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Er zijn geen ondertitels in de taal $1 gevonden voor clip: $2", + "mwe-timedtext-upload-timed-text": "Ondertitels toevoegen" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/nn.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/nn.json new file mode 100644 index 00000000..696c63d4 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/nn.json @@ -0,0 +1,14 @@ +{ + "@metadata": { + "authors": [ + "Njardarlogar" + ] + }, + "mwe-timedtext-layout-off": "Gøym undertekstar", + "mwe-timedtext-textcat-sub": "Undertekstar", + "mwe-timedtext-textcat-lrc": "Tekstar", + "mwe-timedtext-no-subs": "Ingen tekstspor er tilgjengelege", + "mwe-timedtext-language-subtitles-for-clip": "$1 undertekstar for klippet: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Ingen undertekster på $1 vart funne for klippet: $2", + "mwe-timedtext-upload-timed-text": "Legg til undertekstar" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pdc.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pdc.json new file mode 100644 index 00000000..56c9fe84 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pdc.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Xqt" + ] + }, + "mwe-timedtext-back-btn": "Zerrick" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pfl.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pfl.json new file mode 100644 index 00000000..2e41e363 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pfl.json @@ -0,0 +1,7 @@ +{ + "@metadata": { + "authors": [ + "Manuae" + ] + } +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pl.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pl.json new file mode 100644 index 00000000..544812d0 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pl.json @@ -0,0 +1,29 @@ +{ + "@metadata": { + "authors": [ + "BeginaFelicysym", + "Leinad", + "Shadown", + "Sp5uhe" + ] + }, + "mwe-timedtext-back-btn": "Wstecz", + "mwe-timedtext-layout-off": "Ukryj napisy", + "mwe-timedtext-loading-text": "Ładowanie tekstu...", + "mwe-timedtext-textcat-cc": "Podpisy", + "mwe-timedtext-textcat-sub": "Napisy do filmu", + "mwe-timedtext-textcat-tad": "Opis ścieżki dźwiękowej", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-tik": "Notatka", + "mwe-timedtext-textcat-ar": "Aktywne regiony", + "mwe-timedtext-textcat-nb": "Adnotacja", + "mwe-timedtext-textcat-meta": "Metadane ze znacznikami czasu", + "mwe-timedtext-textcat-trx": "Rozpisz", + "mwe-timedtext-textcat-lrc": "Teksty piosenek", + "mwe-timedtext-textcat-lin": "Znaczniki językowe", + "mwe-timedtext-textcat-cue": "Punkty kontrolne", + "mwe-timedtext-no-subs": "Nie ma dostępnych ścieżek tekstowych", + "mwe-timedtext-language-subtitles-for-clip": "$1 napisy do filmu: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Nie odnaleziono $1 napisów do filmu: $2", + "mwe-timedtext-upload-timed-text": "Dodaj napisy" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pms.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pms.json new file mode 100644 index 00000000..7ffca36c --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pms.json @@ -0,0 +1,27 @@ +{ + "@metadata": { + "authors": [ + "Borichèt", + "Dragonòt" + ] + }, + "mwe-timedtext-back-btn": "André", + "mwe-timedtext-layout-off": "Stërmé ij sot-tìtoj", + "mwe-timedtext-loading-text": "Cariament dël test...", + "mwe-timedtext-textcat-cc": "Descrission", + "mwe-timedtext-textcat-sub": "Sot-tìtoj", + "mwe-timedtext-textcat-tad": "Descrission àudio", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-tik": "Test ëd la telescrivent", + "mwe-timedtext-textcat-ar": "Region ative", + "mwe-timedtext-textcat-nb": "Nòta", + "mwe-timedtext-textcat-meta": "Metadat sincronisà", + "mwe-timedtext-textcat-trx": "Trascrission", + "mwe-timedtext-textcat-lrc": "Lìriche", + "mwe-timedtext-textcat-lin": "Marcador lenghìstich", + "mwe-timedtext-textcat-cue": "Pont d'arferiment", + "mwe-timedtext-no-subs": "Gnun-e marche ëd test disponìbij", + "mwe-timedtext-language-subtitles-for-clip": "$1 sot-tìtoj për ël tòch: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "A l'é trovasse gnun sot-tìtoj $1 per ël tòch: $2", + "mwe-timedtext-upload-timed-text": "Gionté dij sot-tìtoj" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ps.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ps.json new file mode 100644 index 00000000..fd556365 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ps.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Ahmed-Najib-Biabani-Ibrahimkhel" + ] + }, + "mwe-timedtext-textcat-ktv": "کارااوکه" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pt-br.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pt-br.json new file mode 100644 index 00000000..008c55ba --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pt-br.json @@ -0,0 +1,30 @@ +{ + "@metadata": { + "authors": [ + "Dianakc", + "Giro720", + "Luckas", + "Luckas Blade", + "555" + ] + }, + "mwe-timedtext-back-btn": "Voltar", + "mwe-timedtext-layout-off": "Ocultar legendas", + "mwe-timedtext-loading-text": "Carregando o texto ...", + "mwe-timedtext-textcat-cc": "Títulos", + "mwe-timedtext-textcat-sub": "Legendas", + "mwe-timedtext-textcat-tad": "Descrição do áudio", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-tik": "Texto deslizante", + "mwe-timedtext-textcat-ar": "Regiões ativas", + "mwe-timedtext-textcat-nb": "Anotação", + "mwe-timedtext-textcat-meta": "Metadados sincronizados", + "mwe-timedtext-textcat-trx": "Transcrição", + "mwe-timedtext-textcat-lrc": "Letra", + "mwe-timedtext-textcat-lin": "Marcação linguística", + "mwe-timedtext-textcat-cue": "Pontos de entrada", + "mwe-timedtext-no-subs": "Não há nenhum texto disponível", + "mwe-timedtext-language-subtitles-for-clip": "Legendas em $1 para o clipe: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Não foram encontradas legendas em $1 para o clipe: $2", + "mwe-timedtext-upload-timed-text": "Adicionar legendas" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pt.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pt.json new file mode 100644 index 00000000..4917da79 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/pt.json @@ -0,0 +1,30 @@ +{ + "@metadata": { + "authors": [ + "Giro720", + "Hamilton Abreu", + "Luckas", + "SandroHc", + "Vitorvicentevalente" + ] + }, + "mwe-timedtext-back-btn": "Voltar", + "mwe-timedtext-layout-off": "Ocultar legendas", + "mwe-timedtext-loading-text": "A carregar o texto ...", + "mwe-timedtext-textcat-cc": "Títulos", + "mwe-timedtext-textcat-sub": "Legendas", + "mwe-timedtext-textcat-tad": "Descrição de áudio", + "mwe-timedtext-textcat-ktv": "Caraoque", + "mwe-timedtext-textcat-tik": "Cotações", + "mwe-timedtext-textcat-ar": "Regiões activas", + "mwe-timedtext-textcat-nb": "Anotação", + "mwe-timedtext-textcat-meta": "Metadados de sincronização", + "mwe-timedtext-textcat-trx": "Transcrição", + "mwe-timedtext-textcat-lrc": "Letra", + "mwe-timedtext-textcat-lin": "Marcação linguística", + "mwe-timedtext-textcat-cue": "Pontos de entrada", + "mwe-timedtext-no-subs": "Não há nenhuma faixa de texto disponível", + "mwe-timedtext-language-subtitles-for-clip": "Legendas em $1 para o clipe: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Não foram encontradas legendas em $1 para o clipe: $2", + "mwe-timedtext-upload-timed-text": "Adicionar legendas" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/qqq.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/qqq.json new file mode 100644 index 00000000..4714d5b1 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/qqq.json @@ -0,0 +1,19 @@ +{ + "@metadata": { + "authors": [ + "EugeneZelenko", + "Shirayuki", + "Siebrand", + "Umherirrender" + ] + }, + "mwe-timedtext-back-btn": "{{Identical|Back}}", + "mwe-timedtext-key-language": "{{optional}}\nParameters:\n* $1 - language key. e.g. \"en\"\n* $2 - language name", + "mwe-timedtext-textcat-cc": "{{Identical|Caption}}", + "mwe-timedtext-textcat-sub": "{{Identical|Subtitle}}", + "mwe-timedtext-textcat-ktv": "See [[w:Karaoke]].", + "mwe-timedtext-textcat-nb": "{{Identical|Annotation}}", + "mwe-timedtext-language-subtitles-for-clip": "$1 is language name for subtitles (e.g. \"English\"), $2 is title of file that timed text is for.\nShown as the page title on a TimedText namespace page when the page exists. See also mwe-timedtext-language-no-subtitles-for-clip.", + "mwe-timedtext-language-no-subtitles-for-clip": "$1 is language name, $2 is title of file that timed text is for.\nShown as the page title on a TimedText namespace page when the page does not exist. See also mwe-timedtext-language-subtitles-for-clip", + "mwe-timedtext-upload-timed-text": "After clicking the 'CC' button on the video player, the button on the resulting menu to add subtitles to a video file." +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ro.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ro.json new file mode 100644 index 00000000..77892ab4 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ro.json @@ -0,0 +1,27 @@ +{ + "@metadata": { + "authors": [ + "Minisarm", + "Stelistcristi" + ] + }, + "mwe-timedtext-back-btn": "Înapoi", + "mwe-timedtext-layout-off": "Ascunde subtitrările", + "mwe-timedtext-loading-text": "Se încarcă textul...", + "mwe-timedtext-textcat-cc": "Legende", + "mwe-timedtext-textcat-sub": "Subtitrări", + "mwe-timedtext-textcat-tad": "Descriere audio", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-tik": "Text mai gros", + "mwe-timedtext-textcat-ar": "Regiuni active", + "mwe-timedtext-textcat-nb": "Adnotare", + "mwe-timedtext-textcat-meta": "Metadate sincronizate", + "mwe-timedtext-textcat-trx": "Transcripție", + "mwe-timedtext-textcat-lrc": "Versuri", + "mwe-timedtext-textcat-lin": "Etichete lingvistice", + "mwe-timedtext-textcat-cue": "Puncte de tac", + "mwe-timedtext-no-subs": "Niciun text de piesă disponibil", + "mwe-timedtext-language-subtitles-for-clip": "Subtitrare în limba $1 pentru clip: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Nu s-a găsit nicio subtitrare în limba $1 pentru clip: $2", + "mwe-timedtext-upload-timed-text": "Adaugă subtitrări" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/roa-tara.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/roa-tara.json new file mode 100644 index 00000000..a26678a4 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/roa-tara.json @@ -0,0 +1,14 @@ +{ + "@metadata": { + "authors": [ + "Joetaras" + ] + }, + "mwe-timedtext-back-btn": "Rrete", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-nb": "Annotazione", + "mwe-timedtext-textcat-meta": "Metadate temborizzate", + "mwe-timedtext-textcat-trx": "Trascrive", + "mwe-timedtext-textcat-lrc": "Teste", + "mwe-timedtext-upload-timed-text": "Aggiunge le sottotitole" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ru.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ru.json new file mode 100644 index 00000000..8b3ff81c --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ru.json @@ -0,0 +1,29 @@ +{ + "@metadata": { + "authors": [ + "MaxSem", + "Okras", + "Александр Сигачёв", + "Kaganer" + ] + }, + "mwe-timedtext-back-btn": "Назад", + "mwe-timedtext-layout-off": "Скрыть субтитры", + "mwe-timedtext-loading-text": "Загрузка текста…", + "mwe-timedtext-textcat-cc": "Субтитры-описания", + "mwe-timedtext-textcat-sub": "Субтитры", + "mwe-timedtext-textcat-tad": "Описание аудиофайла", + "mwe-timedtext-textcat-ktv": "Караоке", + "mwe-timedtext-textcat-tik": "Текстовые карточки", + "mwe-timedtext-textcat-ar": "Активные области", + "mwe-timedtext-textcat-nb": "Аннотация", + "mwe-timedtext-textcat-meta": "Синхронизированные метаданные", + "mwe-timedtext-textcat-trx": "Стенограмма", + "mwe-timedtext-textcat-lrc": "Слова песни", + "mwe-timedtext-textcat-lin": "Лингвистическая разметка", + "mwe-timedtext-textcat-cue": "Знаковые точки", + "mwe-timedtext-no-subs": "Нет текстовых дорожек", + "mwe-timedtext-language-subtitles-for-clip": "$1 — субтитры для клипа: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Не найдено субтитров на $1 для клипа: $2", + "mwe-timedtext-upload-timed-text": "Добавить субтитры" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/rue.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/rue.json new file mode 100644 index 00000000..1cc92d6f --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/rue.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Gazeb" + ] + }, + "mwe-timedtext-back-btn": "Назад" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/si.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/si.json new file mode 100644 index 00000000..8af0327f --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/si.json @@ -0,0 +1,25 @@ +{ + "@metadata": { + "authors": [ + "පසිඳු කාවින්ද" + ] + }, + "mwe-timedtext-back-btn": "ආපසු", + "mwe-timedtext-layout-off": "උපශීර්ෂ සඟවන්න", + "mwe-timedtext-loading-text": "පෙළ පූරණය වෙමින් ...", + "mwe-timedtext-textcat-cc": "උපන්යාස", + "mwe-timedtext-textcat-sub": "උපශීර්ෂ", + "mwe-timedtext-textcat-tad": "ශ්රව්ය විස්තරය", + "mwe-timedtext-textcat-ktv": "කැරෝකේ", + "mwe-timedtext-textcat-tik": "ඔරලෝසු පෙළ", + "mwe-timedtext-textcat-ar": "සක්රිය ප්රදේශ", + "mwe-timedtext-textcat-nb": "ටීකාව", + "mwe-timedtext-textcat-meta": "කාලිත පාරදත්ත", + "mwe-timedtext-textcat-trx": "ප්රතිලේඛනය", + "mwe-timedtext-textcat-lrc": "ගීපදවැල්", + "mwe-timedtext-textcat-lin": "භාෂාමය අධිකය", + "mwe-timedtext-textcat-cue": "ඉංගිත ගතිගුණ", + "mwe-timedtext-no-subs": "මීළඟ පථ ලබාගත නොහැක", + "mwe-timedtext-language-subtitles-for-clip": "ක්ලිපය සඳහා $1 උපසිරුස: $2", + "mwe-timedtext-upload-timed-text": "උපශීර්ෂ එක් කරන්න" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sl.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sl.json new file mode 100644 index 00000000..8df43558 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sl.json @@ -0,0 +1,8 @@ +{ + "@metadata": { + "authors": [ + "Dbc334" + ] + }, + "mwe-timedtext-back-btn": "Nazaj" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/so.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/so.json new file mode 100644 index 00000000..6a979a8b --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/so.json @@ -0,0 +1,7 @@ +{ + "@metadata": { + "authors": [ + "Abshirdheere" + ] + } +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sr-ec.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sr-ec.json new file mode 100644 index 00000000..f3dfbbc6 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sr-ec.json @@ -0,0 +1,15 @@ +{ + "@metadata": { + "authors": [ + "Rancher", + "Михајло Анђелковић" + ] + }, + "mwe-timedtext-back-btn": "Назад", + "mwe-timedtext-layout-off": "Сакриј сабтајтлове", + "mwe-timedtext-loading-text": "Учитава се текст ...", + "mwe-timedtext-key-language": "$1, $2", + "mwe-timedtext-textcat-cc": "Ознаке", + "mwe-timedtext-textcat-sub": "Поднаслови", + "mwe-timedtext-textcat-trx": "Транскрипт" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sr-el.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sr-el.json new file mode 100644 index 00000000..100a6fc3 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sr-el.json @@ -0,0 +1,14 @@ +{ + "@metadata": { + "authors": [ + "Rancher" + ] + }, + "mwe-timedtext-back-btn": "Nazad", + "mwe-timedtext-layout-off": "Sakrij sabtajtlove", + "mwe-timedtext-loading-text": "Učitava se tekst ...", + "mwe-timedtext-key-language": "$1, $2", + "mwe-timedtext-textcat-cc": "Oznake", + "mwe-timedtext-textcat-sub": "Podnaslovi", + "mwe-timedtext-textcat-trx": "Transkript" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sv.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sv.json new file mode 100644 index 00000000..a0b693cd --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/sv.json @@ -0,0 +1,27 @@ +{ + "@metadata": { + "authors": [ + "Ainali", + "Dafer45" + ] + }, + "mwe-timedtext-back-btn": "Tillbaka", + "mwe-timedtext-layout-off": "Dölj undertexter", + "mwe-timedtext-loading-text": "Laddar text ...", + "mwe-timedtext-textcat-cc": "Undertexter", + "mwe-timedtext-textcat-sub": "Undertexter", + "mwe-timedtext-textcat-tad": "Ljudbeskrivning", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-tik": "Rullande text", + "mwe-timedtext-textcat-ar": "Aktiva regioner", + "mwe-timedtext-textcat-nb": "Anmärkning", + "mwe-timedtext-textcat-meta": "Tidsbestämd metadata", + "mwe-timedtext-textcat-trx": "Transkription", + "mwe-timedtext-textcat-lrc": "Texter", + "mwe-timedtext-textcat-lin": "Språkliga markeringar", + "mwe-timedtext-textcat-cue": "Referenspunkter", + "mwe-timedtext-no-subs": "Inga textspår finns", + "mwe-timedtext-language-subtitles-for-clip": "$1 undertexter för klipp: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Inga $1 undertexter hittades för klipp: $2", + "mwe-timedtext-upload-timed-text": "Lägga till undertexter" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ta.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ta.json new file mode 100644 index 00000000..6e9ef3e8 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ta.json @@ -0,0 +1,16 @@ +{ + "@metadata": { + "authors": [ + "Karthi.dr", + "Shanmugamp7", + "மதனாஹரன்" + ] + }, + "mwe-timedtext-back-btn": "பின்செல்", + "mwe-timedtext-layout-off": "துணைத்தலைப்புக்களை மறை", + "mwe-timedtext-loading-text": "உரையை ஏற்றுகிறது ...", + "mwe-timedtext-textcat-sub": "துணைத்தலைப்புக்கள்", + "mwe-timedtext-textcat-tad": "ஒலித விவரணம்", + "mwe-timedtext-textcat-lrc": "பாடல் வரிகள்", + "mwe-timedtext-upload-timed-text": "துணைத்தலைப்புக்களைச் சேர்" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/te.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/te.json new file mode 100644 index 00000000..50688138 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/te.json @@ -0,0 +1,9 @@ +{ + "@metadata": { + "authors": [ + "Veeven" + ] + }, + "mwe-timedtext-back-btn": "వెనక్కి", + "mwe-timedtext-textcat-sub": "ఉపశీర్షికలు" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/tl.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/tl.json new file mode 100644 index 00000000..971a8f30 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/tl.json @@ -0,0 +1,27 @@ +{ + "@metadata": { + "authors": [ + "AnakngAraw" + ] + }, + "mwe-timedtext-back-btn": "Bumalik", + "mwe-timedtext-layout-off": "Itago ang kabahaging mga pamagat", + "mwe-timedtext-loading-text": "Ikinakarga ang teksto ...", + "mwe-timedtext-key-language": "$1, $2", + "mwe-timedtext-textcat-cc": "Mga paliwanag", + "mwe-timedtext-textcat-sub": "Kabahaging mga pamagat", + "mwe-timedtext-textcat-tad": "Paglalarawan ng naririnig", + "mwe-timedtext-textcat-ktv": "Karaoke", + "mwe-timedtext-textcat-tik": "Teksto ng pampulso", + "mwe-timedtext-textcat-ar": "Masisiglang mga rehiyon", + "mwe-timedtext-textcat-nb": "Paliwanag", + "mwe-timedtext-textcat-meta": "Inorasang metadato", + "mwe-timedtext-textcat-trx": "Sipi ng salin", + "mwe-timedtext-textcat-lrc": "Titik ng awit", + "mwe-timedtext-textcat-lin": "Markang-pantaas ng lingguwistika", + "mwe-timedtext-textcat-cue": "Mga tuldok ng pahiwatig", + "mwe-timedtext-no-subs": "Walang makukuhang mga bakas ng teksto", + "mwe-timedtext-language-subtitles-for-clip": "$1 kabahaging mga pamagat para sa putol na: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Walang natagpuang $1 kabahaging mga pamagat para sa putol na: $2", + "mwe-timedtext-upload-timed-text": "Magdagdag ng kabahaging mga pamagat" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/tr.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/tr.json new file mode 100644 index 00000000..8b26730a --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/tr.json @@ -0,0 +1,11 @@ +{ + "@metadata": { + "authors": [ + "Emperyan" + ] + }, + "mwe-timedtext-back-btn": "Geri", + "mwe-timedtext-textcat-sub": "Alt yazılar", + "mwe-timedtext-no-subs": "Parça metni yok", + "mwe-timedtext-upload-timed-text": "Alt yazı ekle" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/uk.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/uk.json new file mode 100644 index 00000000..916f0395 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/uk.json @@ -0,0 +1,27 @@ +{ + "@metadata": { + "authors": [ + "Base", + "Тест" + ] + }, + "mwe-timedtext-back-btn": "Назад", + "mwe-timedtext-layout-off": "Приховати субтитри", + "mwe-timedtext-loading-text": "Завантаження тексту…", + "mwe-timedtext-textcat-cc": "Субтитри-підписи", + "mwe-timedtext-textcat-sub": "Субтитри", + "mwe-timedtext-textcat-tad": "Аудіо-опис", + "mwe-timedtext-textcat-ktv": "Караоке", + "mwe-timedtext-textcat-tik": "Текстові картки", + "mwe-timedtext-textcat-ar": "Активні області", + "mwe-timedtext-textcat-nb": "Анотація", + "mwe-timedtext-textcat-meta": "Синхронізовані метадані", + "mwe-timedtext-textcat-trx": "Стенограма", + "mwe-timedtext-textcat-lrc": "Слова пісні", + "mwe-timedtext-textcat-lin": "Лінгвістична розмітка", + "mwe-timedtext-textcat-cue": "Знакові точки", + "mwe-timedtext-no-subs": "Немає текстових доріжок", + "mwe-timedtext-language-subtitles-for-clip": "$1 — субтитри для кліпу: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Не знайдено субтитрів $1 для кліпу: $2", + "mwe-timedtext-upload-timed-text": "Додати субтитри" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ur.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ur.json new file mode 100644 index 00000000..baafae32 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/ur.json @@ -0,0 +1,9 @@ +{ + "@metadata": { + "authors": [ + "පසිඳු කාවින්ද" + ] + }, + "mwe-timedtext-back-btn": "واپس", + "mwe-timedtext-textcat-sub": "رومانیہ" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/vi.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/vi.json new file mode 100644 index 00000000..5ee9bb9b --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/vi.json @@ -0,0 +1,18 @@ +{ + "@metadata": { + "authors": [ + "Minh Nguyen", + "පසිඳු කාවින්ද" + ] + }, + "mwe-timedtext-back-btn": "Quay lại", + "mwe-timedtext-layout-off": "Ẩn phụ đề", + "mwe-timedtext-loading-text": "Đang tải văn bản…", + "mwe-timedtext-textcat-sub": "Phụ đề", + "mwe-timedtext-textcat-tad": "Lời miêu tả âm thanh", + "mwe-timedtext-textcat-ktv": "Karaôkê", + "mwe-timedtext-textcat-meta": "Siêu dữ liệu đồng bộ", + "mwe-timedtext-textcat-lrc": "Lời hát", + "mwe-timedtext-textcat-lin": "Đánh dấu ngôn ngữ học", + "mwe-timedtext-upload-timed-text": "Thêm phụ đề" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/wa.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/wa.json new file mode 100644 index 00000000..c8d2fdf6 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/wa.json @@ -0,0 +1,15 @@ +{ + "@metadata": { + "authors": [ + "Srtxg" + ] + }, + "mwe-timedtext-layout-off": "Catchî les dzo-tites", + "mwe-timedtext-loading-text": "Dji tchedje li tecse...", + "mwe-timedtext-textcat-cc": "Ledjindes", + "mwe-timedtext-textcat-sub": "Dizo-tites", + "mwe-timedtext-textcat-lrc": "Paroles", + "mwe-timedtext-textcat-lin": "Etiketes di lingaedje", + "mwe-timedtext-language-subtitles-for-clip": "Dizo-tites e $1 pol clip: $2", + "mwe-timedtext-language-no-subtitles-for-clip": "Nou dzo-tite $1 di trové pol clip: $2" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/yi.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/yi.json new file mode 100644 index 00000000..c05e1576 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/yi.json @@ -0,0 +1,9 @@ +{ + "@metadata": { + "authors": [ + "פוילישער" + ] + }, + "mwe-timedtext-back-btn": "צוריק", + "mwe-timedtext-textcat-cc": "באשרייבונגען" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/zh-hans.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/zh-hans.json new file mode 100644 index 00000000..d13683e9 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/zh-hans.json @@ -0,0 +1,30 @@ +{ + "@metadata": { + "authors": [ + "Shizhao", + "Simon Shek", + "Wilsonmess", + "Xiaomingyan", + "Yfdyh000" + ] + }, + "mwe-timedtext-back-btn": "返回", + "mwe-timedtext-layout-off": "隐藏字幕", + "mwe-timedtext-loading-text": "正在载入文本...", + "mwe-timedtext-textcat-cc": "说明", + "mwe-timedtext-textcat-sub": "副标题", + "mwe-timedtext-textcat-tad": "声音说明", + "mwe-timedtext-textcat-ktv": "卡拉OK", + "mwe-timedtext-textcat-tik": "滚动文本", + "mwe-timedtext-textcat-ar": "作用区域", + "mwe-timedtext-textcat-nb": "注释", + "mwe-timedtext-textcat-meta": "字幕元数据", + "mwe-timedtext-textcat-trx": "字幕", + "mwe-timedtext-textcat-lrc": "歌词", + "mwe-timedtext-textcat-lin": "语言标记", + "mwe-timedtext-textcat-cue": "提示点", + "mwe-timedtext-no-subs": "没有可用的字幕", + "mwe-timedtext-language-subtitles-for-clip": "片段$2的$1字幕", + "mwe-timedtext-language-no-subtitles-for-clip": "没有找到片段$2的$1字幕", + "mwe-timedtext-upload-timed-text": "添加字幕" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/zh-hant.json b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/zh-hant.json new file mode 100644 index 00000000..b653aeb1 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/i18n/zh-hant.json @@ -0,0 +1,29 @@ +{ + "@metadata": { + "authors": [ + "Justincheng12345", + "Mark85296341", + "Simon Shek", + "LNDDYL" + ] + }, + "mwe-timedtext-back-btn": "返回", + "mwe-timedtext-layout-off": "隱藏字幕", + "mwe-timedtext-loading-text": "正在讀取文字……", + "mwe-timedtext-textcat-cc": "標題", + "mwe-timedtext-textcat-sub": "副標題", + "mwe-timedtext-textcat-tad": "音訊說明", + "mwe-timedtext-textcat-ktv": "卡拉OK", + "mwe-timedtext-textcat-tik": "滾動文本", + "mwe-timedtext-textcat-ar": "有效區城", + "mwe-timedtext-textcat-nb": "註解", + "mwe-timedtext-textcat-meta": "字幕元資料", + "mwe-timedtext-textcat-trx": "字幕", + "mwe-timedtext-textcat-lrc": "歌詞", + "mwe-timedtext-textcat-lin": "語言標記", + "mwe-timedtext-textcat-cue": "暗點", + "mwe-timedtext-no-subs": "無可用字幕", + "mwe-timedtext-language-subtitles-for-clip": "片段的$1字幕文件:$2", + "mwe-timedtext-language-no-subtitles-for-clip": "沒有找到片段的$1字幕文件:$2", + "mwe-timedtext-upload-timed-text": "添加字幕" +} diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/resources/mw.TextSource.js b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/resources/mw.TextSource.js new file mode 100644 index 00000000..cce8310f --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/resources/mw.TextSource.js @@ -0,0 +1,504 @@ +/** + * Base mw.TextSource object + * + * @param {Object} source Source object to extend + * @param {Object} textProvider [Optional] The text provider interface ( to load source from api ) + */ +( function( mw, $ ) { "use strict"; + + mw.TextSource = function( source ) { + return this.init( source ); + }; + mw.TextSource.prototype = { + + //The load state: + loaded: false, + + // Container for the captions + // captions include "start", "end" and "content" fields + captions: [], + + // The css style for captions ( some file formats specify display types ) + styleCss: {}, + + // The previous index of the timed text served + // Avoids searching the entire array on time updates. + prevIndex: 0, + + /** + * @constructor Inherits mediaSource from embedPlayer + * @param {source} Base source element + * @param {Object} Pointer to the textProvider + */ + init: function( source , textProvider) { + // Inherits mediaSource + for( var i in source){ + this[ i ] = source[ i ]; + } + + // Set default category to subtitle if unset: + if( ! this.kind ) { + this.kind = 'subtitle'; + } + //Set the textProvider if provided + if( textProvider ) { + this.textProvider = textProvider; + } + return this; + }, + + /** + * Function to load and parse the source text + * @param {Function} callback Function called once text source is loaded + */ + load: function( callback ) { + var _this = this; + mw.log("TextSource:: load src "+ _this.getSrc() ); + + // Setup up a callback ( in case it was not defined ) + if( !callback ){ + callback = function(){ return ; }; + } + + // Check if the captions have already been loaded: + if( this.loaded ){ + return callback(); + } + + // Try to load src via XHR source + if( !this.getSrc() ) { + mw.log( "Error: TextSource no source url for text track"); + return callback(); + } + + // Check type for special loaders: + $( mw ).triggerQueueCallback( 'TimedText_LoadTextSource', _this, function(){ + if( _this.loaded ){ + callback(); + } else { + // if no module loaded the text source use the normal ajax proxy: + new mw.ajaxProxy({ + url: _this.getSrc(), + success: function( resultXML ) { + _this.captions = _this.getCaptions( resultXML ); + _this.loaded = true; + mw.log("mw.TextSource :: loaded from " + _this.getSrc() + " Found: " + _this.captions.length + ' captions' ); + callback(); + }, + error: function() { + mw.log("Error: TextSource Error with http response"); + _this.loaded = true; + callback(); + } + }); + } + }) + }, + /** + * Returns the text content for requested time + * + * @param {Number} time Time in seconds + */ + getCaptionForTime: function ( time ) { + var prevCaption = this.captions[ this.prevIndex ]; + var captionSet = {}; + + // Setup the startIndex: + if( prevCaption && time >= prevCaption.start ) { + var startIndex = this.prevIndex; + }else{ + // If a backwards seek start searching at the start: + var startIndex = 0; + } + var firstCapIndex = 0; + // Start looking for the text via time, add all matches that are in range + for( var i = startIndex ; i < this.captions.length; i++ ) { + var caption = this.captions[ i ]; + // Don't handle captions with 0 or -1 end time: + if( caption.end == 0 || caption.end == -1) + continue; + + if( time >= caption.start && + time <= caption.end ) { + // set the earliest valid time to the current start index: + if( !firstCapIndex ){ + firstCapIndex = caption.start; + } + + //mw.log("Start cap time: " + caption.start + ' End time: ' + caption.end ); + captionSet[i] = caption ; + } + // captions are stored in start order stop search if we get larger than time + if( caption.start > time ){ + break; + } + } + // Update the prevIndex: + this.prevIndex = firstCapIndex; + //Return the set of captions in range: + return captionSet; + }, + + /** + * Check if the caption is an overlay format ( and must be ontop of the player ) + */ + isOverlay: function(){ + return this.mimeType == 'text/xml'; + }, + + getCaptions: function( data ){ + // Detect caption data type: + switch( this.mimeType ){ + case 'text/mw-srt': + return this.getCaptiosnFromMediaWikiSrt( data ); + break; + case 'text/x-srt': + return this.getCaptionsFromSrt( data); + break; + case 'text/xml': + return this.getCaptionsFromTMML( data ); + break; + } + // caption mime not found return empty set: + return []; + }, + + getStyleCssById: function( styleId ){ + if( this.styleCss[ styleId ] ){ + return this.styleCss[ styleId ]; + } + return {}; + }, + /** + * Grab timed text from TMML format + * + * @param data + * @return + */ + getCaptionsFromTMML: function( data ){ + var _this = this; + mw.log("TextSource::getCaptionsFromTMML", data); + // set up display information: + var captions = []; + var xml = ( $( data ).find("tt").length ) ? data : $.parseXML( data ); + + // Check for parse error: + try { + if( !xml || $( xml ).find('parsererror').length ){ + mw.log("Error: close caption parse error: " + $( xml ).find('parsererror').text() ); + return captions; + } + } catch ( e ) { + mw.log( "Error: close caption parse error: " + e.toString() ); + return captions; + } + + // Set the body Style + var bodyStyleId = $( xml ).find('body').attr('style'); + + // Set style translate ttml to css + $( xml ).find( 'style').each( function( inx, style){ + var cssObject = {}; + // Map CamelCase css properties: + $( style.attributes ).each(function(inx, attr){ + var attrName = attr.name; + if( attrName.substr(0, 4) !== 'tts:' ){ + // skip + return true; + } + var cssName = ''; + for( var c = 4; c < attrName.length; c++){ + if( attrName[c].toLowerCase() != attrName[c] ){ + cssName += '-' + attrName[c].toLowerCase(); + } else { + cssName+= attrName[c] + } + } + cssObject[ cssName ] = attr.nodeValue; + }); + // for(var i =0; i< style.length ) + _this.styleCss[ $( style).attr('id') ] = cssObject; + }); + + $( xml ).find( 'p' ).each( function( inx, p ){ + // Get text content by converting ttml node to html + var content = ''; + $.each( p.childNodes, function(inx, node){ + content+= _this.convertTTML2HTML( node ); + }); + // Get the end time: + var end = null; + if( $( p ).attr( 'end' ) ){ + end = mw.npt2seconds( $( p ).attr( 'end' ) ); + } + // Look for dur + if( !end && $( p ).attr( 'dur' )){ + end = mw.npt2seconds( $( p ).attr( 'begin' ) ) + + mw.npt2seconds( $( p ).attr( 'dur' ) ); + } + + // Create the caption object : + var captionObj ={ + 'start': mw.npt2seconds( $( p ).attr( 'begin' ) ), + 'end': end, + 'content': content + }; + + // See if we have custom metadata for position of this caption object + // there are 35 columns across and 15 rows high + var $meta = $(p).find( 'metadata' ); + if( $meta.length ){ + captionObj['css'] = { + 'position': 'absolute' + }; + if( $meta.attr('cccol') ){ + captionObj['css']['left'] = ( $meta.attr('cccol') / 35 ) * 100 +'%'; + // also means the width has to be reduced: + //captionObj['css']['width'] = 100 - parseInt( captionObj['css']['left'] ) + '%'; + } + if( $meta.attr('ccrow') ){ + captionObj['css']['top'] = ( $meta.attr('ccrow') / 15 ) * 100 +'%'; + } + } + if( $(p).attr('tts:textAlign') ){ + if( !captionObj['css'] ){ + captionObj['css'] = {}; + } + captionObj['css']['text-align'] = $(p).attr('tts:textAlign'); + + // Remove text align is "right" flip the css left: + if( captionObj['css']['text-align'] == 'right' && captionObj['css']['left'] ){ + //captionObj['css']['width'] = captionObj['css']['left']; + captionObj['css']['left'] = null; + } + } + + // check if this p has any style else use the body parent + if( $(p).attr('style') ){ + captionObj['styleId'] = $(p).attr('style') ; + } else { + captionObj['styleId'] = bodyStyleId; + } + captions.push( captionObj); + }); + return captions; + }, + convertTTML2HTML: function( node ){ + var _this = this; + + // look for text node: + if( node.nodeType == 3 ){ + return node.textContent; + } + // skip metadata nodes: + if( node.nodeName == 'metadata' ){ + return ''; + } + // if a br just append + if( node.nodeName == 'br' ){ + return '<br />'; + } + // Setup tts mappings TODO should be static property of a ttmlSource object. + var ttsStyleMap = { + 'tts:color' : 'color', + 'tts:fontWeight' : 'font-weight', + 'tts:fontStyle' : 'font-style' + }; + if( node.childNodes.length ){ + var nodeString = ''; + var styleVal = ''; + for( var attr in ttsStyleMap ){ + if( node.getAttribute( attr ) ){ + styleVal+= ttsStyleMap[ attr ] + ':' + node.getAttribute( attr ) + ';'; + } + } + nodeString += '<' + node.nodeName + ' style="' + styleVal + '" >'; + $.each( node.childNodes, function( inx, childNode ){ + nodeString += _this.convertTTML2HTML( childNode ); + }); + nodeString += '</' + node.nodeName + '>'; + return nodeString; + } + }, + /** + * srt timed text parse handle: + * @param {String} data Srt string to be parsed + */ + getCaptionsFromSrt: function ( data ){ + mw.log("TextSource::getCaptionsFromSrt"); + var _this = this; + // Check if the "srt" parses as an XML + try{ + var xml = $.parseXML( data ); + if( xml && $( xml ).find('parsererror').length == 0 ){ + return this.getCaptionsFromTMML( data ); + } + } catch ( e ){ + // srt should not be xml + } + // Remove dos newlines + var srt = data.replace(/\r+/g, ''); + + // Trim white space start and end + srt = srt.replace(/^\s+|\s+$/g, ''); + + // Remove all html tags for security reasons + srt = srt.replace(/<[a-zA-Z\/][^>]*>/g, ''); + + // Get captions + var captions = []; + var caplist = srt.split('\n\n'); + for (var i = 0; i < caplist.length; i++) { + var captionText = ""; + var caption = false; + captionText = caplist[i]; + var s = captionText.split(/\n/); + if (s.length < 2) { + // file format error or comment lines + continue; + } + if (s[0].match(/^\d+$/) && s[1].match(/\d+:\d+:\d+/)) { + // ignore caption number in s[0] + // parse time string + var m = s[1].match(/(\d+):(\d+):(\d+)(?:,(\d+))?\s*--?>\s*(\d+):(\d+):(\d+)(?:,(\d+))?/); + if (m) { + caption = _this.match2caption( m ); + } else { + // Unrecognized timestring + continue; + } + if( caption ){ + // concatenate text lines to html text + caption['content'] = s.slice(2).join("<br>"); + } + } else { + // file format error or comment lines + continue; + } + // Add the current caption to the captions set: + captions.push( caption ); + } + + return captions; + }, + + /** + * Get srts from a mediawiki html / srt string + * + * Right now wiki -> html is not always friendly to our srt parsing. + * The long term plan is to move the srt parsing to server side and have the api + * server up the srt's times in JSON form + * + * Also see https://bugzilla.wikimedia.org/show_bug.cgi?id=29126 + * + * TODO move to mediaWiki specific module. + */ + getCaptiosnFromMediaWikiSrt: function( data ){ + mw.log("TimedText::getCaptiosnFromMediaWikiSrt:"); + var _this = this; + var captions = [ ]; + var curentCap = { + 'content': '' + }; + var parseNextAsTime = false; + // Note this string concatenation and html error wrapping sometimes causes + // parse issues where the wikitext includes many native <p /> tags without child + // subtitles. In prating this is not a deal breakers because the wikitext for + // TimedText namespace and associated srts already has a specific format. + // Long term we will move to server side parsing. + $( '<div>' + data + '</div>' ).find('p').each( function() { + var currentPtext = $(this).html(); + //mw.log( 'pText: ' + currentPtext ); + + // We translate raw wikitext gennerated html into a matched srt time sample. + // The raw html looks like: + // # + // hh:mm:ss,ms --> hh:mm:ss,ms + // text + // + // You can read more about the srt format here: + // http://en.wikipedia.org/wiki/SubRip + // + // We attempt to be fairly robust in our regular expression to catch a few + // srt variations such as omition of commas and empty text lines. + var m = currentPtext + .replace('-->', '-->') // restore --> with --> for easier srt parsing: + .match(/\d+\s([\d\-]+):([\d\-]+):([\d\-]+)(?:,([\d\-]+))?\s*--?>\s*([\d\-]+):([\d\-]+):([\d\-]+)(?:,([\d\-]+))?\n?(.*)/); + + if (m) { + captions.push( + _this.match2caption( m ) + ); + return true; + } + + /*** + * Handle multi line sytle output + * + * Handles cases parse cases where an entire line can't be parsed in the single + * regular expression above, Since the diffrent captions pars are outputed in + * diffrent <p /> tags by the wikitext parser output. + */ + + // Check if we have reached the end of a multi line match + if( parseInt( currentPtext ) == currentPtext ) { + if( curentCap.content != '' ) { + captions.push( curentCap ); + } + // Clear out the current caption content + curentCap = { + 'content': '' + }; + return true; + } + // Check only for time match: + var m = currentPtext + .replace('-->', '-->') + .match(/(\d+):(\d+):(\d+)(?:,(\d+))?\s*--?>\s*(\d+):(\d+):(\d+)(?:,(\d+))?/); + if (m) { + // Update the currentCap: + curentCap = _this.match2caption( m ); + return true; + } + // Else append contnet for the curentCap + if( currentPtext != '<br>' ) { + curentCap['content'] += currentPtext; + } + }); + //Push last subtitle: + if( curentCap.length != 0) { + captions.push( curentCap ); + } + mw.log( "TimedText::getCaptiosnFromMediaWikiSrt found " + captions.length + ' captions'); + return captions; + }, + /** + * Takes a regular expresion match and converts it to a caption object + */ + match2caption: function( m ){ + var caption = {}; + // Look for ms: + var startMs = (m[4]) ? parseInt(m[4], 10) : 0; + var endMs = (m[8]) ? parseInt(m[8], 10) : 0; + caption['start'] = this.timeParts2seconds( m[1], m[2], m[3], startMs ); + caption['end'] = this.timeParts2seconds( m[5], m[6], m[7], endMs ); + if( m[9] ){ + caption['content'] = $.trim( m[9] ); + } + return caption; + }, + /** + * Takes time parts in hours, min, seconds and milliseconds and coverts to float seconds. + */ + timeParts2seconds: function( hours, min, sec, ms ){ + return mw.measurements2seconds({ + 'hours': hours, + 'minutes': min, + 'seconds' : sec, + 'milliseconds': ms + }); + } + }; + + +} )( mediaWiki, jQuery ); diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/resources/mw.TimedText.js b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/resources/mw.TimedText.js new file mode 100644 index 00000000..2a69343e --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/resources/mw.TimedText.js @@ -0,0 +1,1313 @@ +/** + * The Core timed Text interface object + * + * handles class mappings for: + * menu display ( jquery.ui themeable ) + * timed text loading request + * timed text edit requests + * timed text search & seek interface ( version 2 ) + * + * @author: Michael Dale + * + */ + +( function( mw, $ ) {"use strict"; + + // Merge in timed text related attributes: + mw.mergeConfig( 'EmbedPlayer.SourceAttributes', [ + 'srclang', + 'kind', + 'label' + ]); + + /** + * Timed Text Object + * @param embedPlayer Host player for timedText interfaces + */ + mw.TimedText = function( embedPlayer ) { + return this.init( embedPlayer ); + }; + + mw.TimedText.prototype = { + + /** + * Preferences config order is presently: + * 1) user cookie + * 2) defaults provided in this config var: + */ + config: { + // Layout for basic "timedText" type can be 'ontop', 'off', 'below' + 'layout' : 'ontop', + + //Set the default local ( should be grabbed from the browser ) + 'userLanguage' : mw.config.get( 'wgUserLanguage' ) || 'en', + + //Set the default kind of timedText to display ( un-categorized timed-text is by default "subtitles" ) + 'userKind' : 'subtitles' + }, + + // The default display mode is 'ontop' + defaultDisplayMode : 'ontop', + + // Save last layout mode + lastLayout : 'ontop', + + // The bind prefix: + bindPostFix: '.timedText', + + // Default options are empty + options: {}, + + /** + * The list of enabled sources + */ + enabledSources: [], + + // First loading flag - To set the layout at first load + firstLoad: true, + + /** + * The current language key + */ + currentLangKey : null, + + /** + * The direction of the current language + */ + currentLangDir : null, + + /** + * Stores the last text string per kind to avoid dom checks for updated text + */ + prevText: [], + + /** + * Text sources ( a set of textSource objects ) + */ + textSources: [], + + /** + * Valid "Track" categories + */ + validCategoriesKeys: [ + "CC", + "SUB", + "TAD", + "KTV", + "TIK", + "AR", + "NB", + "META", + "TRX", + "LRC", + "LIN", + "CUE" + ], + + /** + * @constructor + * @param {Object} embedPlayer Host player for timedText interfaces + */ + init: function( embedPlayer ) { + var _this = this; + mw.log("TimedText: init() "); + this.embedPlayer = embedPlayer; + // don't display captions on native player: + if( embedPlayer.useNativePlayerControls() ){ + return this; + } + + // Load user preferences config: + var preferenceConfig = $.cookie( 'TimedText.Preferences' ); + if( preferenceConfig !== "false" && preferenceConfig != null ) { + this.config = JSON.parse( preferenceConfig ); + } + // remove any old bindings on change media: + $( this.embedPlayer ).bind( 'onChangeMedia' + this.bindPostFix , function(){ + _this.destroy(); + }); + + // Remove any old bindings before we add the current bindings: + _this.destroy(); + + // Add player bindings + _this.addPlayerBindings(); + return this; + }, + destroy: function(){ + // remove any old player bindings; + $( this.embedPlayer ).unbind( this.bindPostFix ); + // Clear out enabled sources: + this.enabledSources = []; + // Clear out text sources: + this.textSources = []; + }, + /** + * Add timed text related player bindings + * @return + */ + addPlayerBindings: function(){ + var _this = this; + var embedPlayer = this.embedPlayer; + + // Check for timed text support: + _this.addInterface(); + + $( embedPlayer ).bind( 'timeupdate' + this.bindPostFix, function( event, jEvent, id ) { + // regain scope + _this = $('#' + id)[0].timedText; + // monitor text updates + _this.monitor(); + } ); + + $( embedPlayer ).bind( 'firstPlay' + this.bindPostFix, function(event, id ) { + // regain scope + _this = $('#' + id)[0].timedText; + // Will load and setup timedText sources (if not loaded already loaded ) + _this.setupTextSources(); + // Hide the caption menu if presently displayed + $( '#textMenuContainer_' + _this.embedPlayer.id ).hide(); + } ); + + // Re-Initialize when changing media + $( embedPlayer ).bind( 'onChangeMedia' + this.bindPostFix, function() { + _this.destroy(); + _this.updateLayout(); + _this.setupTextSources(); + $( '#textMenuContainer_' + embedPlayer.id ).hide(); + } ); + + // Resize the timed text font size per window width + $( embedPlayer ).bind( 'onCloseFullScreen' + this.bindPostFix + ' onOpenFullScreen' + this.bindPostFix, function() { + // Check if we are in fullscreen or not, if so add an additional bottom offset of + // double the default bottom padding. + var textOffset = _this.embedPlayer.controlBuilder.inFullScreen ? + mw.config.get("TimedText.BottomPadding") * 2 : + mw.config.get("TimedText.BottomPadding"); + + var textCss = _this.getInterfaceSizeTextCss({ + 'width' : embedPlayer.getInterface().width(), + 'height' : embedPlayer.getInterface().height() + }); + + mw.log( 'TimedText::set text size for: : ' + embedPlayer.getInterface().width() + ' = ' + textCss['font-size'] ); + if ( embedPlayer.controlBuilder.isOverlayControls() && !embedPlayer.getInterface().find( '.control-bar' ).is( ':hidden' ) ) { + textOffset += _this.embedPlayer.controlBuilder.getHeight(); + } + embedPlayer.getInterface().find( '.track' ) + .css( textCss ) + .css({ + // Get the text size scale then set it to control bar height + TimedText.BottomPadding; + 'bottom': textOffset + 'px' + }); + }); + + // Update the timed text size + $( embedPlayer ).bind( 'updateLayout'+ this.bindPostFix, function() { + // If the the player resize action is an animation, animate text resize, + // else instantly adjust the css. + var textCss = _this.getInterfaceSizeTextCss( { + 'width': embedPlayer.getPlayerWidth(), + 'height': embedPlayer.getPlayerHeight() + }); + mw.log( 'TimedText::updateLayout: ' + textCss['font-size']); + embedPlayer.getInterface().find( '.track' ).css( textCss ); + }); + + // Setup display binding + $( embedPlayer ).bind( 'onShowControlBar'+ this.bindPostFix, function(event, layout, id ){ + // update embedPlayer ref: + var embedPlayer = $('#' + id )[0]; + if ( embedPlayer.controlBuilder.isOverlayControls() ) { + // Move the text track if present + embedPlayer.getInterface().find( '.track' ) + .stop() + .animate( layout, 'fast' ); + } + }); + + $( embedPlayer ).bind( 'onHideControlBar' + this.bindPostFix, function(event, layout, id ){ + var embedPlayer = $('#' + id )[0]; + if ( embedPlayer.controlBuilder.isOverlayControls() ) { + // Move the text track down if present + embedPlayer.getInterface().find( '.track' ) + .stop() + .animate( layout, 'fast' ); + } + }); + + $( embedPlayer ).bind( 'AdSupport_StartAdPlayback' + this.bindPostFix, function() { + if ( $( '#textMenuContainer_' + embedPlayer.id ).length ) { + $( '#textMenuContainer_' + embedPlayer.id ).hide(); + } + var $textButton = embedPlayer.getInterface().find( '.timed-text' ); + if ( $textButton.length ) { + $textButton.unbind( 'click' ); + } + _this.lastLayout = _this.getLayoutMode(); + _this.setLayoutMode( 'off' ); + } ); + + $( embedPlayer ).bind( 'AdSupport_EndAdPlayback' + this.bindPostFix, function() { + var $textButton = embedPlayer.getInterface().find( '.timed-text' ); + if ( $textButton.length ) { + _this.bindTextButton( $textButton ); + } + _this.setLayoutMode( _this.lastLayout ); + } ); + + }, + addInterface: function(){ + var _this = this; + // By default we include a button in the control bar. + $( _this.embedPlayer ).bind( 'addControlBarComponent' + this.bindPostFix, function(event, controlBar ){ + if( controlBar.supportedComponents['timedText'] !== false && + _this.includeCaptionButton() ) { + controlBar.supportedComponents['timedText'] = true; + controlBar.components['timedText'] = _this.getTimedTextButton(); + } + }); + }, + includeCaptionButton:function(){ + return mw.config.get( 'TimedText.ShowInterface' ) == 'always' || + this.embedPlayer.getTextTracks().length; + }, + /** + * Get the current language key + * @return + * @type {string} + */ + getCurrentLangKey: function(){ + return this.currentLangKey; + }, + /** + * Get the current language direction + * @return + * @type {string} + */ + getCurrentLangDir: function(){ + if ( !this.currentLangDir ) { + var source = this.getSourceByLanguage( this.getCurrentLangKey() ); + this.currentLangDir = source.dir; + } + return this.currentLangDir; + }, + + /** + * The timed text button to be added to the interface + */ + getTimedTextButton: function(){ + var _this = this; + /** + * The closed captions button + */ + return { + 'w': 30, + 'position': 6.9, + 'o': function( ctrlObj ) { + var $textButton = $( '<div />' ) + .attr( 'title', mw.msg( 'mwe-embedplayer-timed_text' ) ) + .addClass( "ui-state-default ui-corner-all ui-icon_link rButton timed-text" ) + .append( + $( '<span />' ) + .addClass( "ui-icon ui-icon-comment" ) + ) + // Captions binding: + .buttonHover(); + _this.bindTextButton( $textButton ); + return $textButton; + + } + }; + }, + bindTextButton: function( $textButton ){ + var _this = this; + $textButton.unbind('click.textMenu').bind('click.textMenu', function() { + _this.showTextMenu(); + return true; + } ); + }, + + /** + * Get the fullscreen text css + */ + getInterfaceSizeTextCss: function( size ) { + //mw.log(' win size is: ' + $( window ).width() + ' ts: ' + textSize ); + return { + 'font-size' : this.getInterfaceSizePercent( size ) + '%' + }; + }, + + /** + * Show the text interface library and show the text interface near the player. + */ + showTextMenu: function() { + var embedPlayer = this.embedPlayer; + var loc = embedPlayer.getInterface().find( '.rButton.timed-text' ).offset(); + mw.log('TimedText::showTextMenu:: ' + embedPlayer.id + ' location: ', loc); + // TODO: Fix menu animation + var $menuButton = this.embedPlayer.getInterface().find( '.timed-text' ); + // Check if a menu has already been built out for the menu button: + if ( $menuButton[0].m ) { + $menuButton.embedMenu( 'show' ); + } else { + // Bind the text menu: + this.buildMenu( true ); + } + }, + getTextMenuContainer: function(){ + var textMenuId = 'textMenuContainer_' + this.embedPlayer.id; + if( !$( '#' + textMenuId ).length ){ + //Setup the menu: + this.embedPlayer.getInterface().append( + $('<div>') + .addClass('ui-widget ui-widget-content ui-corner-all') + .attr( 'id', textMenuId ) + .css( { + 'position' : 'absolute', + 'height' : '180px', + 'width' : '180px', + 'font-size' : '12px', + 'display' : 'none', + 'overflow' : 'auto' + } ) + + ); + } + return $( '#' + textMenuId ); + }, + /** + * Gets a text size percent relative to about 30 columns of text for 400 + * pixel wide player, at 100% text size. + * + * @param size {object} The size of the target player area width and height + */ + getInterfaceSizePercent: function( size ) { + // This is a ugly hack we should read "original player size" and set based + // on some standard ish normal 31 columns 15 rows + var sizeFactor = 4; + if( size.height / size.width < .7 ){ + sizeFactor = 6; + } + var textSize = size.width / sizeFactor; + if( textSize < 95 ){ + textSize = 95; + } + if( textSize > 150 ){ + textSize = 150; + } + return textSize; + }, + + /** + * Setups available text sources + * loads text sources + * auto-selects a source based on the user language + * @param {Function} callback Function to be called once text sources are setup. + */ + setupTextSources: function( callback ) { + mw.log( 'TimedText::setupTextSources'); + var _this = this; + // Load textSources + _this.loadTextSources( function() { + // Enable a default source and issue a request to "load it" + _this.autoSelectSource(); + + // Load and parse the text value of enabled text sources: + _this.loadEnabledSources(); + + if( callback ) { + callback(); + } + } ); + }, + + /** + * Binds the timed text menu + * and updates its content from "getMainMenu" + * + * @param {Object} target to display the menu + * @param {Boolean} autoShow If the menu should be displayed + */ + buildMenu: function( autoShow ) { + var _this = this; + var embedPlayer = this.embedPlayer; + // Setup text sources ( will callback inline if already loaded ) + _this.setupTextSources( function() { + var $menuButton = _this.embedPlayer.getInterface().find( '.timed-text' ); + + var positionOpts = { }; + if( _this.embedPlayer.supports[ 'overlays' ] ){ + var positionOpts = { + 'directionV' : 'up', + 'offsetY' : _this.embedPlayer.controlBuilder.getHeight(), + 'directionH' : 'left', + 'offsetX' : -28 + }; + } + + if( !_this.embedPlayer.getInterface() ){ + mw.log("TimedText:: interface called before interface ready, just wait for interface"); + return ; + } + var $menuButton = _this.embedPlayer.getInterface().find( '.timed-text' ); + var ctrlObj = _this.embedPlayer.controlBuilder; + // NOTE: Button target should be an option or config + $menuButton.embedMenu( { + 'content' : _this.getMainMenu(), + 'zindex' : mw.config.get( 'EmbedPlayer.FullScreenZIndex' ) + 2, + 'crumbDefaultText' : ' ', + 'autoShow': autoShow, + 'keepPosition' : true, + 'showSpeed': 0, + 'height' : 100, + 'width' : 300, + 'targetMenuContainer' : _this.getTextMenuContainer(), + 'positionOpts' : positionOpts, + 'backLinkText' : mw.msg( 'mwe-timedtext-back-btn' ), + 'createMenuCallback' : function(){ + var $interface = _this.embedPlayer.getInterface(); + var $textContainer = _this.getTextMenuContainer(); + var textHeight = 130; + var top = $interface.height() - textHeight - ctrlObj.getHeight() - 6; + if( top < 0 ){ + top = 0; + } + // check for audio + if( _this.embedPlayer.isAudio() ){ + top = _this.embedPlayer.controlBuilder.getHeight() + 4; + } + $textContainer.css({ + 'top' : top, + 'height': textHeight, + 'position' : 'absolute', + 'left': $menuButton[0].offsetLeft - 165, + 'bottom': ctrlObj.getHeight() + }) + ctrlObj.showControlBar( true ); + }, + 'closeMenuCallback' : function(){ + ctrlObj.restoreControlsHover(); + } + }); + }); + }, + + /** + * Monitor video time and update timed text filed[s] + */ + monitor: function() { + //mw.log(" timed Text monitor: " + this.enabledSources.length ); + var embedPlayer = this.embedPlayer; + // Setup local reference to currentTime: + var currentTime = embedPlayer.currentTime; + + // Get the text per kind + var textCategories = [ ]; + + var source = this.enabledSources[ 0 ]; + if( source ) { + this.updateSourceDisplay( source, currentTime ); + } + }, + + /** + * Load all the available text sources from the inline embed + * @param {Function} callback Function to call once text sources are loaded + */ + loadTextSources: function( callback ) { + var _this = this; + // check if text sources are already loaded ( not em ) + if( this.textSources.length ){ + callback( this.textSources ); + return ; + } + this.textSources = []; + // load inline text sources: + $.each( this.embedPlayer.getTextTracks(), function( inx, textSource ){ + _this.textSources.push( new mw.TextSource( textSource ) ); + }); + // return the callback with sources + callback( _this.textSources ); + }, + + /** + * Get the layout mode + * + * Takes into consideration: + * Playback method overlays support ( have to put subtitles below video ) + * + */ + getLayoutMode: function() { + // Re-map "ontop" to "below" if player does not support + if( this.config.layout == 'ontop' && !this.embedPlayer.supports['overlays'] ) { + this.config.layout = 'below'; + } + return this.config.layout; + }, + + /** + * Auto selects a source given the local configuration + * + * NOTE: presently this selects a "single" source. + * In the future we could support multiple "enabled sources" + */ + autoSelectSource: function() { + var _this = this; + // If a source is enabled then don't auto select + if ( this.enabledSources.length ) { + return false; + } + this.enabledSources = []; + + var setDefault = false; + // Check if any source is marked default: + $.each( this.textSources, function(inx, source){ + if( source['default'] ){ + _this.enableSource( source ); + setDefault = true; + return false; + } + }); + if ( setDefault ) { + return true; + } + + var setLocalPref = false; + // Check if any source matches our "local" pref + $.each( this.textSources, function(inx, source){ + if( _this.config.userLanguage == source.srclang.toLowerCase() + && + _this.config.userKind == source.kind + ) { + _this.enableSource( source ); + setLocalPref = true; + return false; + } + }); + if ( setLocalPref ) { + return true; + } + + var setEnglish = false; + // If no userLang, source try enabling English: + if( this.enabledSources.length == 0 ) { + for( var i=0; i < this.textSources.length; i++ ) { + var source = this.textSources[ i ]; + if( source.srclang.toLowerCase() == 'en' ) { + _this.enableSource( source ); + setEnglish = true; + return false; + } + } + } + if ( setEnglish ) { + return true; + } + + var setFirst = false; + // If still no source try the first source we get; + if( this.enabledSources.length == 0 ) { + for( var i=0; i < this.textSources.length; i++ ) { + var source = this.textSources[ i ]; + _this.enableSource( source ); + setFirst = true; + return false; + } + } + if ( setFirst ) { + return true; + } + + return false; + }, + /** + * Enable a source and update the currentLangKey + * @param {object} source + * @return + */ + enableSource: function( source ){ + var _this = this; + // check if we have any source set yet: + if( !_this.enabledSources.length ){ + _this.enabledSources.push( source ); + _this.currentLangKey = source.srclang; + _this.currentLangDir = null; + return ; + } + var sourceEnabled = false; + // Make sure the source is not already enabled + $.each( this.enabledSources, function( inx, enabledSource ){ + if( source.id == enabledSource.id ){ + sourceEnabled = true; + } + }); + if ( !sourceEnabled ) { + _this.enabledSources.push( source ); + _this.currentLangKey = source.srclang; + _this.currentLangDir = null; + } + }, + + /** + * Get the current source sub captions + * @param {function} callback function called once source is loaded + */ + loadCurrentSubSource: function( callback ){ + mw.log("loadCurrentSubSource:: enabled source:" + this.enabledSources.length); + for( var i =0; i < this.enabledSources.length; i++ ){ + var source = this.enabledSources[i]; + if( source.kind == 'SUB' ){ + source.load( function(){ + callback( source); + return ; + }); + } + } + return false; + }, + + /** + * Get sub captions by language key: + * + * @param {string} langKey Key of captions to load + * @pram {function} callback function called once language key is loaded + */ + getSubCaptions: function( langKey, callback ){ + for( var i=0; i < this.textSources.length; i++ ) { + var source = this.textSources[ i ]; + if( source.srclang.toLowerCase() === langKey ) { + var source = this.textSources[ i ]; + source.load( function(){ + callback( source.captions ); + }); + } + } + }, + + /** + * Issue a request to load all enabled Sources + * Should be called anytime enabled Source list is updated + */ + loadEnabledSources: function() { + var _this = this; + mw.log( "TimedText:: loadEnabledSources " + this.enabledSources.length ); + $.each( this.enabledSources, function( inx, enabledSource ) { + // check if the source requires ovelray ( ontop ) layout mode: + if( enabledSource.isOverlay() && _this.config.layout== 'ontop' ){ + _this.setLayoutMode( 'ontop' ); + } + enabledSource.load(function(){ + // Trigger the text loading event: + $( _this.embedPlayer ).trigger('loadedTextSource', enabledSource); + }); + }); + }, + /** + * Checks if a source is "on" + * @return {Boolean} + * true if source is on + * false if source is off + */ + isSourceEnabled: function( source ) { + // no source is "enabled" if subtitles are "off" + if( this.getLayoutMode() == 'off' ){ + return false; + } + var isEnabled = false; + $.each( this.enabledSources, function( inx, enabledSource ) { + if( source.id ) { + if( source.id === enabledSource.id ){ + isEnabled = true; + } + } + if( source.src ){ + if( source.src == enabledSource.src ){ + isEnabled = true; + } + } + }); + return isEnabled; + }, + + /** + * Marks the active captions in the menu + */ + markActive: function( source ) { + var $menu = $( '#textMenuContainer_' + this.embedPlayer.id ); + if ( $menu.length ) { + var $captionRows = $menu.find( '.captionRow' ); + if ( $captionRows.length ) { + $captionRows.each( function() { + $( this ).removeClass( 'ui-icon-bullet ui-icon-radio-on' ); + var iconClass = ( $( this ).data( 'caption-id' ) === source.id ) ? 'ui-icon-bullet' : 'ui-icon-radio-on'; + $( this ).addClass( iconClass ); + } ); + } + } + }, + + /** + * Marks the active layout mode in the menu + */ + markLayoutActive: function ( layoutMode ) { + var $menu = $( '#textMenuContainer_' + this.embedPlayer.id ); + if ( $menu.length ) { + var $layoutRows = $menu.find( '.layoutRow' ); + if ( $layoutRows.length ) { + $layoutRows.each( function() { + $( this ).removeClass( 'ui-icon-bullet ui-icon-radio-on' ); + var iconClass = ( $( this ).data( 'layoutMode' ) === layoutMode ) ? 'ui-icon-bullet' : 'ui-icon-radio-on'; + $( this ).addClass( iconClass ); + } ); + } + } + }, + + /** + * Get a source object by language, returns "false" if not found + * @param {string} langKey The language key filter for selected source + */ + getSourceByLanguage: function ( langKey ) { + for(var i=0; i < this.textSources.length; i++) { + var source = this.textSources[ i ]; + if( source.srclang == langKey ){ + return source; + } + } + return false; + }, + + /** + * Builds the core timed Text menu and + * returns the binded jquery object / dom set + * + * Assumes text sources have been setup: ( _this.setupTextSources() ) + * + * calls a few sub-functions: + * Basic menu layout: + * Chose Language + * All Subtiles here ( if we have categories list them ) + * Layout + * Below video + * Ontop video ( only available to supported plugins ) + * TODO features: + * [ Search Text ] + * [ This video ] + * [ All videos ] + * [ Chapters ] seek to chapter + */ + getMainMenu: function() { + var _this = this; + + // Set the menut to avaliable languages: + var $menu = _this.getLanguageMenu(); + + if( _this.textSources.length == 0 ){ + $menu.append( + $.getLineItem( mw.msg( 'mwe-timedtext-no-subs'), 'close' ) + ); + } else { + // Layout Menu option if not in an iframe and we can expand video size: + $menu.append( + $.getLineItem( + mw.msg( 'mwe-timedtext-layout-off'), + ( _this.getLayoutMode() == 'off' ) ? 'bullet' : 'radio-on', + function() { + _this.setLayoutMode( 'off' ); + }, + 'layoutRow', + { 'layoutMode' : 'off' } + ) + ) + } + // Allow other modules to add to the timed text menu: + $( _this.embedPlayer ).trigger( 'TimedText_BuildCCMenu', [ $menu, _this.embedPlayer.id ] ) ; + + // Test if only one menu item move its children to the top level + if( $menu.children('li').length == 1 ){ + $menu.find('li > ul > li').detach().appendTo( $menu ); + $menu.find('li').eq(0).remove(); + } + + return $menu; + }, + + /** + * Utility function to assist in menu build out: + * Get menu line item (li) html: <li><a> msgKey </a></li> + * + * @param {String} msgKey Msg key for menu item + */ + + /** + * Get line item (li) from source object + * @param {Object} source Source to get menu line item from + */ + getLiSource: function( source ) { + var _this = this; + //See if the source is currently "on" + var sourceIcon = ( this.isSourceEnabled( source ) )? 'bullet' : 'radio-on'; + if( source.title ) { + return $.getLineItem( source.title, sourceIcon, function() { + _this.selectTextSource( source ); + }, 'captionRow', { 'caption-id' : source.id } ); + } + if( source.srclang ) { + var langKey = source.srclang.toLowerCase(); + return $.getLineItem( + mw.msg('mwe-timedtext-key-language', langKey, _this.getLanguageName ( langKey ) ), + sourceIcon, + function() { + // select the current text source: + _this.selectTextSource( source ); + }, + 'captionRow', + { 'caption-id' : source.id } + ); + } + }, + + /** + * Get language name from language key + * @param {String} lang_key Language key + */ + getLanguageName: function( lang_key ) { + if( mw.Language.names[ lang_key ]) { + return mw.Language.names[ lang_key ]; + } + return false; + }, + + + /** + * set the layout mode + * @param {Object} layoutMode The selected layout mode + */ + setLayoutMode: function( layoutMode ) { + var _this = this; + mw.log("TimedText:: setLayoutMode: " + layoutMode + ' ( old mode: ' + _this.config.layout + ' )' ); + if( ( layoutMode != _this.config.layout ) || _this.firstLoad ) { + // Update the config and redraw layout + _this.config.layout = layoutMode; + // Update the display: + _this.updateLayout(); + _this.firstLoad = false; + } + _this.markLayoutActive( layoutMode ); + }, + + toggleCaptions: function(){ + mw.log( "TimedText:: toggleCaptions was:" + this.config.layout ); + if( this.config.layout == 'off' ){ + this.setLayoutMode( this.defaultDisplayMode ); + } else { + this.setLayoutMode( 'off' ); + } + }, + /** + * Updates the timed text layout ( should be called when config.layout changes ) + */ + updateLayout: function() { + mw.log( "TimedText:: updateLayout " ); + var $playerTarget = this.embedPlayer.getInterface(); + if( $playerTarget ) { + // remove any existing caption containers: + $playerTarget.find('.captionContainer,.captionsOverlay').remove(); + } + this.refreshDisplay(); + }, + + /** + * Select a new source + * + * @param {Object} source Source object selected + */ + selectTextSource: function( source ) { + var _this = this; + mw.log("TimedText:: selectTextSource: select lang: " + source.srclang ); + + // enable last non-off layout: + _this.setLayoutMode( _this.lastLayout ); + + // For some reason we lose binding for the menu ~sometimes~ re-bind + this.bindTextButton( this.embedPlayer.getInterface().find('timed-text') ); + + this.currentLangKey = source.srclang; + this.currentLangDir = null; + + // Update the config language if the source includes language + if( source.srclang ){ + this.config.userLanguage = source.srclang; + } + + if( source.kind ){ + this.config.userKind = source.kind; + } + + // (@@todo update kind & setup kind language buckets? ) + + // Remove any other sources selected in sources kind + this.enabledSources = []; + + this.enabledSources.push( source ); + + // Set any existing text target to "loading" + if( !source.loaded ) { + var $playerTarget = this.embedPlayer.getInterface(); + $playerTarget.find('.track').text( mw.msg('mwe-timedtext-loading-text') ); + // Load the text: + source.load( function(){ + // Refresh the interface: + _this.refreshDisplay(); + }); + } else { + _this.refreshDisplay(); + } + + _this.markActive( source ); + + // Trigger the event + $( this.embedPlayer ).trigger( 'TimedText_ChangeSource' ); + }, + + /** + * Refresh the display, updates the timedText layout, menu, and text display + * also updates the cookie preference. + * + * Called after a user option change + */ + refreshDisplay: function() { + // Update the configuration object + $.cookie( 'TimedText.Preferences', JSON.stringify( this.config ) ); + + // Empty out previous text to force an interface update: + this.prevText = []; + + // Refresh the Menu (if it has a target to refresh) + mw.log( 'TimedText:: bind menu refresh display' ); + this.buildMenu(); + this.resizeInterface(); + + // add an empty catption: + this.displayTextTarget( $( '<span /> ').text( '') ); + + // Issues a "monitor" command to update the timed text for the new layout + this.monitor(); + }, + + /** + * Builds the language source list menu + * Cehck if the "track" tags had the "kind" attribute. + * + * The kind attribute forms "categories" of text tracks like "subtitles", + * "audio description", "chapter names". We check for these categories + * when building out the language menu. + */ + getLanguageMenu: function() { + var _this = this; + + // See if we have categories to worry about + // associative array of SUB etc categories. Each kind contains an array of textSources. + var categorySourceList = {}; + var sourcesWithCategoryCount = 0; + + // ( All sources should have a kind (depreciate ) + var sourcesWithoutCategory = [ ]; + for( var i=0; i < this.textSources.length; i++ ) { + var source = this.textSources[ i ]; + if( source.kind ) { + var categoryKey = source.kind ; + // Init Category menu item if it does not already exist: + if( !categorySourceList[ categoryKey ] ) { + // Set up catList pointer: + categorySourceList[ categoryKey ] = []; + sourcesWithCategoryCount++; + } + // Append to the source kind key menu item: + categorySourceList[ categoryKey ].push( + _this.getLiSource( source ) + ); + }else{ + sourcesWithoutCategory.push( _this.getLiSource( source ) ); + } + } + var $langMenu = $('<ul>'); + // Check if we have multiple categories ( if not just list them under the parent menu item) + if( sourcesWithCategoryCount > 1 ) { + for(var categoryKey in categorySourceList) { + var $catChildren = $('<ul>'); + for(var i=0; i < categorySourceList[ categoryKey ].length; i++) { + $catChildren.append( + categorySourceList[ categoryKey ][i] + ); + } + // Append a cat menu item for each kind list + // Give grep a chance to find the usages: + // mwe-timedtext-textcat-cc, mwe-timedtext-textcat-sub, mwe-timedtext-textcat-tad, + // mwe-timedtext-textcat-ktv, mwe-timedtext-textcat-tik, mwe-timedtext-textcat-ar, + // mwe-timedtext-textcat-nb, mwe-timedtext-textcat-meta, mwe-timedtext-textcat-trx, + // mwe-timedtext-textcat-lrc, mwe-timedtext-textcat-lin, mwe-timedtext-textcat-cue + $langMenu.append( + $.getLineItem( mw.msg( 'mwe-timedtext-textcat-' + categoryKey.toLowerCase() ) ).append( + $catChildren + ) + ); + } + } else { + for(var categoryKey in categorySourceList) { + for(var i=0; i < categorySourceList[ categoryKey ].length; i++) { + $langMenu.append( + categorySourceList[ categoryKey ][i] + ); + } + } + } + // Add any remaning sources that did nto have a category + for(var i=0; i < sourcesWithoutCategory.length; i++) { + $langMenu.append( sourcesWithoutCategory[i] ); + } + + return $langMenu; + }, + + /** + * Updates a source display in the interface for a given time + * @param {object} source Source to update + * @param {number} time Caption time used to add and remove active captions. + */ + updateSourceDisplay: function ( source, time ) { + var _this = this; + if( this.timeOffset ){ + time = time + parseInt( this.timeOffset ); + } + + // Get the source text for the requested time: + var activeCaptions = source.getCaptionForTime( time ); + var addedCaption = false; + // Show captions that are on: + $.each( activeCaptions, function( capId, caption ){ + var $cap = _this.embedPlayer.getInterface().find( '.track[data-capId="' + capId +'"]'); + if( caption.content != $cap.html() ){ + // remove old + $cap.remove(); + // add the updated value: + _this.addCaption( source, capId, caption ); + addedCaption = true; + } + }); + + // hide captions that are off: + _this.embedPlayer.getInterface().find( '.track' ).each(function( inx, caption){ + if( !activeCaptions[ $( caption ).attr('data-capId') ] ){ + if( addedCaption ){ + $( caption ).remove(); + } else { + $( caption ).fadeOut( mw.config.get('EmbedPlayer.MonitorRate'), function(){$(this).remove();} ); + } + } + }); + }, + addCaption: function( source, capId, caption ){ + if( this.getLayoutMode() == 'off' ){ + return ; + } + + // use capId as a class instead of id for easy selections and no conflicts with + // multiple players on page. + var $textTarget = $('<div />') + .addClass( 'track' ) + .attr( 'data-capId', capId ) + .hide(); + + // Update text ( use "html" instead of "text" so that subtitle format can + // include html formating + // TOOD we should scrub this for non-formating html + $textTarget.append( + $('<span>') + .addClass( 'ttmlStyled' ) + .css( 'pointer-events', 'auto') + .css( this.getCaptionCss() ) + .append( + $('<span>') + // Prevent background (color) overflowing TimedText + // http://stackoverflow.com/questions/9077887/avoid-overlapping-rows-in-inline-element-with-a-background-color-applied + .css( 'position', 'relative' ) + .html( caption.content ) + ) + ); + + + // Add/update the lang option + $textTarget.attr( 'lang', source.srclang.toLowerCase() ); + + // Update any links to point to a new window + $textTarget.find( 'a' ).attr( 'target', '_blank' ); + + // Add TTML or other complex text styles / layouts if we have ontop captions: + if( this.getLayoutMode() == 'ontop' ){ + if( caption.css ){ + $textTarget.css( caption.css ); + } else { + $textTarget.css( this.getDefaultStyle() ); + } + } + // Apply any custom style ( if we are ontop of the video ) + this.displayTextTarget( $textTarget ); + + // apply any interface size adjustments: + $textTarget.css( this.getInterfaceSizeTextCss({ + 'width' : this.embedPlayer.getInterface().width(), + 'height' : this.embedPlayer.getInterface().height() + }) + ); + + // Update the style of the text object if set + if( caption.styleId ){ + var capCss = source.getStyleCssById( caption.styleId ); + $textTarget.find('span.ttmlStyled').css( + capCss + ); + } + $textTarget.fadeIn('fast'); + }, + displayTextTarget: function( $textTarget ){ + var embedPlayer = this.embedPlayer; + var $interface = embedPlayer.getInterface(); + var controlBarHeight = embedPlayer.controlBuilder.getHeight(); + + if( this.getLayoutMode() == 'off' ){ + // sync player size per audio player: + if( embedPlayer.isAudio() ){ + $interface.find( '.overlay-win' ).css( 'top', controlBarHeight ); + $interface.css( 'height', controlBarHeight ); + } + return; + } + + if( this.getLayoutMode() == 'ontop' ){ + this.addTextOverlay( + $textTarget + ); + } else if( this.getLayoutMode() == 'below' ){ + this.addTextBelowVideo( $textTarget ); + } else { + mw.log("Possible Error, layout mode not recognized: " + this.getLayoutMode() ); + } + + // sync player size per audio player: + if( embedPlayer.isAudio() && embedPlayer.getInterface().height() < 80 ){ + $interface.find( '.overlay-win' ).css( 'top', 80); + $interface.css( 'height', 80 ); + + $interface.find('.captionsOverlay' ) + .css('bottom', embedPlayer.controlBuilder.getHeight() ) + } + + }, + getDefaultStyle: function(){ + var defaultBottom = 15; + if( this.embedPlayer.controlBuilder.isOverlayControls() && !this.embedPlayer.getInterface().find( '.control-bar' ).is( ':hidden' ) ) { + defaultBottom += this.embedPlayer.controlBuilder.getHeight(); + } + var baseCss = { + 'position':'absolute', + 'bottom': defaultBottom, + 'width': '100%', + 'display': 'block', + 'opacity': .8, + 'text-align': 'center' + }; + baseCss =$.extend( baseCss, this.getInterfaceSizeTextCss({ + 'width' : this.embedPlayer.getInterface().width(), + 'height' : this.embedPlayer.getInterface().height() + })); + return baseCss; + }, + addTextOverlay: function( $textTarget ){ + var _this = this; + var $captionsOverlayTarget = this.embedPlayer.getInterface().find('.captionsOverlay'); + var layoutCss = { + 'left': 0, + 'top': 0, + 'bottom': 0, + 'right': 0, + 'position': 'absolute', + 'direction': this.getCurrentLangDir(), + 'z-index': mw.config.get( 'EmbedPlayer.FullScreenZIndex' ) + }; + + if( $captionsOverlayTarget.length == 0 ){ + // TODO make this look more like addBelowVideoCaptionsTarget + $captionsOverlayTarget = $( '<div />' ) + .addClass( 'captionsOverlay' ) + .css( layoutCss ) + .css('pointer-events', 'none'); + this.embedPlayer.getVideoHolder().append( $captionsOverlayTarget ); + } + // Append the text: + $captionsOverlayTarget.append( $textTarget ); + + }, + /** + * Applies the default layout for a text target + */ + addTextBelowVideo: function( $textTarget ) { + var $playerTarget = this.embedPlayer.getInterface(); + // Get the relative positioned player class from the controlBuilder: + this.embedPlayer.controlBuilder.keepControlBarOnScreen = true; + if( !$playerTarget.find('.captionContainer').length || this.embedPlayer.useNativePlayerControls() ) { + this.addBelowVideoCaptionContainer(); + } + $playerTarget.find('.captionContainer').html( + $textTarget.css( { + 'color':'white' + } ) + ); + }, + addBelowVideoCaptionContainer: function(){ + var _this = this; + mw.log( "TimedText:: addBelowVideoCaptionContainer" ); + var $playerTarget = this.embedPlayer.getInterface(); + if( $playerTarget.find('.captionContainer').length ) { + return ; + } + // Append after video container + this.embedPlayer.getVideoHolder().after( + $('<div>').addClass( 'captionContainer block' ) + .css({ + 'width' : '100%', + 'height' : mw.config.get( 'TimedText.BelowVideoBlackBoxHeight' ) + 'px', + 'background-color' : '#000', + 'text-align' : 'center', + 'padding-top' : '5px' + } ) + ); + + _this.embedPlayer.triggerHelper('updateLayout'); + }, + /** + * Resize the interface for layoutMode == 'below' ( if not in full screen) + */ + resizeInterface: function(){ + var _this = this; + if( !_this.embedPlayer.controlBuilder ){ + // too soon + return ; + } + if( !_this.embedPlayer.controlBuilder.inFullScreen && _this.originalPlayerHeight ){ + _this.embedPlayer.triggerHelper( 'resizeIframeContainer', [{'height' : _this.originalPlayerHeight}] ); + } else { + // removed resize on container content, since syncPlayerSize calls now handle keeping player aspect. + _this.embedPlayer.triggerHelper('updateLayout'); + } + }, + /** + * Build css for caption using this.options + */ + getCaptionCss: function() { + return {}; + } + }; + +} )( mediaWiki, jQuery ); diff --git a/extensions/TimedMediaHandler/MwEmbedModules/TimedText/resources/mw.style.TimedText.css b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/resources/mw.style.TimedText.css new file mode 100644 index 00000000..e924ba34 --- /dev/null +++ b/extensions/TimedMediaHandler/MwEmbedModules/TimedText/resources/mw.style.TimedText.css @@ -0,0 +1,18 @@ +.ttmlStyled { + color: white; + letter-spacing: 0.04em; + text-align: center; + padding: 0.2em; + /* + // Text shadow is too slow with current browsers use background-color + text-shadow:0 2px 1px #000000, -1px 3px 1px #000000, -2px 2px 1px #000000, -2px 1px 1px #000000, -2px 0 1px #000000, 2px 2px 1px #000000, 1px 2px 1px #000000, 0 -2px 1px #000000, 2px -2px 1px #000000, -2px -1px 1px #000000, -1px -3px 1px #000000, -3px -2px 1px #000000, 0 0 25px #000000, 0 0 35px #000000, 0 0 35px #000000, 0 0 31px #FFFFFF, 0 0 31px #FFFFFF, 0 0 31px #FFFFFF; + */ + background-color: #333; +} +.ttmlStyled a { + text-decoration: none; + color : #BBF; +} +.ttmlStyled a:visited{ + color : #BBF; +} |