Use ISO 639 for languages
authorChocobozzz <me@florianbigard.com>
Mon, 23 Apr 2018 12:39:52 +0000 (14:39 +0200)
committerChocobozzz <me@florianbigard.com>
Mon, 23 Apr 2018 12:39:52 +0000 (14:39 +0200)
25 files changed:
client/src/app/core/server/server.service.ts
client/src/app/shared/video/video-edit.model.ts
client/src/app/shared/video/video.model.ts
package.json
server/helpers/custom-validators/activitypub/videos.ts
server/helpers/custom-validators/videos.ts
server/helpers/database-utils.ts
server/initializers/constants.ts
server/initializers/migrations/0210-video-language.ts [new file with mode: 0644]
server/lib/activitypub/videos.ts
server/models/video/video.ts
server/tests/api/check-params/videos.ts
server/tests/api/server/follows.ts
server/tests/api/server/handle-down.ts
server/tests/api/videos/multiple-servers.ts
server/tests/api/videos/single-server.ts
server/tests/real-world/real-world.ts
server/tests/utils/videos/videos.ts
server/tools/import-videos.ts
server/tools/upload.ts
shared/models/videos/video-create.model.ts
shared/models/videos/video-update.model.ts
shared/models/videos/video.model.ts
support/doc/api/openapi.yaml
yarn.lock

index a8beb242dc48dcb6fc819c3a0d4068763926e704..a71c6d0bfbd74811ecc443a0f4592fb979ae0b32 100644 (file)
@@ -6,6 +6,7 @@ import { ReplaySubject } from 'rxjs/ReplaySubject'
 import { ServerConfig } from '../../../../../shared'
 import { About } from '../../../../../shared/models/server/about.model'
 import { environment } from '../../../environments/environment'
+import { VideoConstant, VideoPrivacy } from '../../../../../shared/models/videos'
 
 @Injectable()
 export class ServerService {
@@ -57,10 +58,10 @@ export class ServerService {
       videoQuota: -1
     }
   }
-  private videoCategories: Array<{ id: number, label: string }> = []
-  private videoLicences: Array<{ id: number, label: string }> = []
-  private videoLanguages: Array<{ id: number, label: string }> = []
-  private videoPrivacies: Array<{ id: number, label: string }> = []
+  private videoCategories: Array<VideoConstant<number>> = []
+  private videoLicences: Array<VideoConstant<number>> = []
+  private videoLanguages: Array<VideoConstant<string>> = []
+  private videoPrivacies: Array<VideoConstant<VideoPrivacy>> = []
 
   constructor (private http: HttpClient) {
     this.loadConfigLocally()
@@ -118,7 +119,7 @@ export class ServerService {
 
   private loadVideoAttributeEnum (
     attributeName: 'categories' | 'licences' | 'languages' | 'privacies',
-    hashToPopulate: { id: number, label: string }[],
+    hashToPopulate: VideoConstant<number | string>[],
     notifier: ReplaySubject<boolean>,
     sort = false
   ) {
@@ -127,7 +128,7 @@ export class ServerService {
          Object.keys(data)
                .forEach(dataKey => {
                  hashToPopulate.push({
-                   id: parseInt(dataKey, 10),
+                   id: dataKey,
                    label: data[dataKey]
                  })
                })
index c1a70d1b36ada555342c08df91957a370425410f..39826d71e2d2791e71716eec0c7b3563c6c6eaa2 100644 (file)
@@ -4,7 +4,7 @@ import { VideoPrivacy } from '../../../../../shared/models/videos/video-privacy.
 export class VideoEdit {
   category: number
   licence: number
-  language: number
+  language: string
   description: string
   name: string
   tags: string[]
index e25c172e0315ec98dad13819f3082bd853edb801..a284c1688fcde9c3c8f23462b7699a8b60a65bb2 100644 (file)
@@ -13,7 +13,7 @@ export class Video implements VideoServerModel {
   publishedAt: Date
   category: VideoConstant<number>
   licence: VideoConstant<number>
-  language: VideoConstant<number>
+  language: VideoConstant<string>
   privacy: VideoConstant<VideoPrivacy>
   description: string
   duration: number
index 5f7299b9d03212442794655ef1db4e42fdc6138c..5776f9fc6497f1f318f822791f58a9c3a565abcd 100644 (file)
@@ -69,6 +69,7 @@
     "express-rate-limit": "^2.11.0",
     "express-validator": "^5.0.0",
     "fluent-ffmpeg": "^2.1.0",
+    "iso-639-3": "^1.0.1",
     "js-yaml": "^3.5.4",
     "jsonld": "^1.0.1",
     "jsonld-signatures": "https://github.com/Chocobozzz/jsonld-signatures#rsa2017",
index d8986b2a0a6e3ffc42795bb215dc246126080398..8ec7df49a4610273a6b68fd5e72f8aec77d78501 100644 (file)
@@ -49,9 +49,9 @@ function isVideoTorrentObjectValid (video: any) {
     isActivityPubVideoDurationValid(video.duration) &&
     isUUIDValid(video.uuid) &&
     setValidRemoteTags(video) &&
-    (!video.category || isRemoteIdentifierValid(video.category)) &&
-    (!video.licence || isRemoteIdentifierValid(video.licence)) &&
-    (!video.language || isRemoteIdentifierValid(video.language)) &&
+    (!video.category || isRemoteNumberIdentifierValid(video.category)) &&
+    (!video.licence || isRemoteNumberIdentifierValid(video.licence)) &&
+    (!video.language || isRemoteStringIdentifierValid(video.language)) &&
     isVideoViewsValid(video.views) &&
     isBooleanValid(video.sensitive) &&
     isBooleanValid(video.commentsEnabled) &&
@@ -72,6 +72,7 @@ export {
   isVideoTorrentCreateActivityValid,
   isVideoTorrentUpdateActivityValid,
   isVideoTorrentDeleteActivityValid,
+  isRemoteStringIdentifierValid,
   isVideoFlagValid,
   isVideoTorrentObjectValid
 }
@@ -89,10 +90,14 @@ function setValidRemoteTags (video: any) {
   return true
 }
 
-function isRemoteIdentifierValid (data: any) {
+function isRemoteNumberIdentifierValid (data: any) {
   return validator.isInt(data.identifier, { min: 0 })
 }
 
+function isRemoteStringIdentifierValid (data: any) {
+  return typeof data.identifier === 'string'
+}
+
 function isRemoteVideoContentValid (mediaType: string, content: string) {
   return mediaType === 'text/markdown' && isVideoTruncatedDescriptionValid(content)
 }
index a46d715ba8cf89d90b6ef4a69d9a48297ddf7d32..23d2d8ac6aa380af3e4c2f9818563a31e03b38f6 100644 (file)
@@ -18,16 +18,17 @@ import { exists, isArray, isFileValid } from './misc'
 const VIDEOS_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEOS
 const VIDEO_ABUSES_CONSTRAINTS_FIELDS = CONSTRAINTS_FIELDS.VIDEO_ABUSES
 
-function isVideoCategoryValid (value: number) {
+function isVideoCategoryValid (value: any) {
   return value === null || VIDEO_CATEGORIES[value] !== undefined
 }
 
-function isVideoLicenceValid (value: number) {
+function isVideoLicenceValid (value: any) {
   return value === null || VIDEO_LICENCES[value] !== undefined
 }
 
-function isVideoLanguageValid (value: number) {
-  return value === null || VIDEO_LANGUAGES[value] !== undefined
+function isVideoLanguageValid (value: any) {
+  return value === null ||
+    (typeof value === 'string' && validator.isLength(value, VIDEOS_CONSTRAINTS_FIELDS.LANGUAGE))
 }
 
 function isVideoDurationValid (value: string) {
index 47a0abfd206a9462ba019afa4cd5fb2339b88d9a..b3ff42a37b2c68541dd503d008e3f66d1c48f741 100644 (file)
@@ -28,7 +28,7 @@ function transactionRetryer <T> (func: (err: any, data: T) => any) {
 
       errorFilter: err => {
         const willRetry = (err.name === 'SequelizeDatabaseError')
-        logger.debug('Maybe retrying the transaction function.', { willRetry })
+        logger.debug('Maybe retrying the transaction function.', { willRetry, err })
         return willRetry
       }
     }, func, (err, data) => err ? rej(err) : res(data))
index d1915586ae78537c044ca195c9b811dfbfd425b6..9c9c3afc0944651bb362670d5719ac5cbec50e9f 100644 (file)
@@ -13,7 +13,7 @@ let config: IConfig = require('config')
 
 // ---------------------------------------------------------------------------
 
-const LAST_MIGRATION_VERSION = 205
+const LAST_MIGRATION_VERSION = 210
 
 // ---------------------------------------------------------------------------
 
@@ -196,6 +196,7 @@ const CONSTRAINTS_FIELDS = {
   },
   VIDEOS: {
     NAME: { min: 3, max: 120 }, // Length
+    LANGUAGE: { min: 1, max: 10 }, // Length
     TRUNCATED_DESCRIPTION: { min: 3, max: 250 }, // Length
     DESCRIPTION: { min: 3, max: 10000 }, // Length
     SUPPORT: { min: 3, max: 300 }, // Length
@@ -291,38 +292,7 @@ const VIDEO_LICENCES = {
   7: 'Public Domain Dedication'
 }
 
-// See https://en.wikipedia.org/wiki/List_of_languages_by_number_of_native_speakers#Nationalencyklopedin
-const VIDEO_LANGUAGES = {
-  1: 'English',
-  2: 'Spanish',
-  3: 'Mandarin',
-  4: 'Hindi',
-  5: 'Arabic',
-  6: 'Portuguese',
-  7: 'Bengali',
-  8: 'Russian',
-  9: 'Japanese',
-  10: 'Punjabi',
-  11: 'German',
-  12: 'Korean',
-  13: 'French',
-  14: 'Italian',
-  1000: 'Sign Language',
-  1001: 'American Sign Language',
-  1002: 'Arab Sign Language',
-  1003: 'British Sign Language',
-  1004: 'Brazilian Sign Language',
-  1005: 'Chinese Sign Language',
-  1006: 'Czech Sign Language',
-  1007: 'Danish Sign Language',
-  1008: 'French Sign Language',
-  1009: 'German Sign Language',
-  1010: 'Indo-Pakistani Sign Language',
-  1011: 'Japanese Sign Language',
-  1012: 'South African Sign Language',
-  1013: 'Swedish Sign Language',
-  1014: 'Russian Sign Language'
-}
+const VIDEO_LANGUAGES = buildLanguages()
 
 const VIDEO_PRIVACIES = {
   [VideoPrivacy.PUBLIC]: 'Public',
@@ -521,6 +491,40 @@ function updateWebserverConfig () {
   CONFIG.WEBSERVER.HOST = sanitizeHost(CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT, REMOTE_SCHEME.HTTP)
 }
 
+function buildLanguages () {
+  const iso639 = require('iso-639-3')
+
+  const languages: { [ id: string ]: string } = {}
+
+  const signLanguages = [
+    'sgn', // Sign languages (macro language)
+    'ase', // American
+    'sdl', // Arabian
+    'bfi', // British
+    'bzs', // Brazilian
+    'csl', // Chinese
+    'cse', // Czech
+    'dsl', // Danish
+    'fsl', // French
+    'gsg', // German
+    'pks', // Pakistan
+    'jsl', // Japanese
+    'sfs', // South African
+    'swl', // Swedish
+    'rsl' // Russian
+  ]
+
+  // Only add ISO639-1 languages and some sign languages (ISO639-3)
+  iso639
+    .filter(l => {
+      return (l.iso6391 !== null && l.type === 'living') ||
+        signLanguages.indexOf(l.iso6393) !== -1
+    })
+    .forEach(l => languages[l.iso6391 || l.iso6393] = l.name)
+
+  return languages
+}
+
 export function reloadConfig () {
 
   function directory () {
diff --git a/server/initializers/migrations/0210-video-language.ts b/server/initializers/migrations/0210-video-language.ts
new file mode 100644 (file)
index 0000000..b7ec909
--- /dev/null
@@ -0,0 +1,162 @@
+import * as Sequelize from 'sequelize'
+import { CONSTRAINTS_FIELDS } from '../index'
+
+async function up (utils: {
+  transaction: Sequelize.Transaction,
+  queryInterface: Sequelize.QueryInterface,
+  sequelize: Sequelize.Sequelize
+}): Promise<void> {
+
+  {
+    await utils.queryInterface.renameColumn('video', 'language', 'oldLanguage')
+  }
+
+  {
+    const data = {
+      type: Sequelize.STRING(CONSTRAINTS_FIELDS.VIDEOS.LANGUAGE.max),
+      allowNull: true,
+      defaultValue: null
+    }
+    await utils.queryInterface.addColumn('video', 'language', data)
+  }
+
+  {
+    const languages = [
+      {
+        oldLanguage: 1,
+        newLanguage: 'en'
+      },
+      {
+        oldLanguage: 2,
+        newLanguage: 'es'
+      },
+      {
+        oldLanguage: 3,
+        newLanguage: 'zh'
+      },
+      {
+        oldLanguage: 4,
+        newLanguage: 'hi'
+      },
+      {
+        oldLanguage: 5,
+        newLanguage: 'ar'
+      },
+      {
+        oldLanguage: 6,
+        newLanguage: 'pt'
+      },
+      {
+        oldLanguage: 7,
+        newLanguage: 'bn'
+      },
+      {
+        oldLanguage: 8,
+        newLanguage: 'ru'
+      },
+      {
+        oldLanguage: 9,
+        newLanguage: 'ja'
+      },
+      {
+        oldLanguage: 10,
+        newLanguage: 'pa'
+      },
+      {
+        oldLanguage: 11,
+        newLanguage: 'de'
+      },
+      {
+        oldLanguage: 12,
+        newLanguage: 'ko'
+      },
+      {
+        oldLanguage: 13,
+        newLanguage: 'fr'
+      },
+      {
+        oldLanguage: 14,
+        newLanguage: 'it'
+      },
+      {
+        oldLanguage: 1000,
+        newLanguage: 'sgn'
+      },
+      {
+        oldLanguage: 1001,
+        newLanguage: 'ase'
+      },
+      {
+        oldLanguage: 1002,
+        newLanguage: 'sdl'
+      },
+      {
+        oldLanguage: 1003,
+        newLanguage: 'bfi'
+      },
+      {
+        oldLanguage: 1004,
+        newLanguage: 'bzs'
+      },
+      {
+        oldLanguage: 1005,
+        newLanguage: 'csl'
+      },
+      {
+        oldLanguage: 1006,
+        newLanguage: 'cse'
+      },
+      {
+        oldLanguage: 1007,
+        newLanguage: 'dsl'
+      },
+      {
+        oldLanguage: 1008,
+        newLanguage: 'fsl'
+      },
+      {
+        oldLanguage: 1009,
+        newLanguage: 'gsg'
+      },
+      {
+        oldLanguage: 1010,
+        newLanguage: 'pks'
+      },
+      {
+        oldLanguage: 1011,
+        newLanguage: 'jsl'
+      },
+      {
+        oldLanguage: 1012,
+        newLanguage: 'sfs'
+      },
+      {
+        oldLanguage: 1013,
+        newLanguage: 'swl'
+      },
+      {
+        oldLanguage: 1014,
+        newLanguage: 'rsl'
+      }
+    ]
+
+    for (const language of languages) {
+      const query = 'UPDATE "video" SET "language" = \'' + language.newLanguage + '\' WHERE "oldLanguage" = ' + language.oldLanguage
+      await utils.sequelize.query(query)
+    }
+  }
+
+  {
+    await utils.queryInterface.removeColumn('video', 'oldLanguage')
+  }
+
+}
+
+function down (options) {
+  throw new Error('Not implemented.')
+}
+
+export {
+  up,
+  down
+}
index ffba1570b07ee35a8318a11ac7207fb22ddfef86..7cb1fe24028f09543ed492baa29c795d88bb2385 100644 (file)
@@ -58,19 +58,19 @@ async function videoActivityObjectToDBAttributes (videoChannel: VideoChannelMode
                                                   videoObject: VideoTorrentObject,
                                                   to: string[] = []) {
   const privacy = to.indexOf(ACTIVITY_PUB.PUBLIC) !== -1 ? VideoPrivacy.PUBLIC : VideoPrivacy.UNLISTED
-
   const duration = videoObject.duration.replace(/[^\d]+/, '')
-  let language = null
+
+  let language: string = null
   if (videoObject.language) {
-    language = parseInt(videoObject.language.identifier, 10)
+    language = videoObject.language.identifier
   }
 
-  let category = null
+  let category: number = null
   if (videoObject.category) {
     category = parseInt(videoObject.category.identifier, 10)
   }
 
-  let licence = null
+  let licence: number = null
   if (videoObject.licence) {
     licence = parseInt(videoObject.licence.identifier, 10)
   }
index aef75d2062cb920469e10e318296755e50566ed8..b0fff65268fd8542153fb16649ab6f915cfd42a7 100644 (file)
@@ -322,8 +322,8 @@ export class VideoModel extends Model<VideoModel> {
   @AllowNull(true)
   @Default(null)
   @Is('VideoLanguage', value => throwIfNotValid(value, isVideoLanguageValid, 'language'))
-  @Column
-  language: number
+  @Column(DataType.STRING(CONSTRAINTS_FIELDS.VIDEOS.LANGUAGE.max))
+  language: string
 
   @AllowNull(false)
   @Is('VideoPrivacy', value => throwIfNotValid(value, isVideoPrivacyValid, 'privacy'))
@@ -877,8 +877,10 @@ export class VideoModel extends Model<VideoModel> {
     return licenceLabel
   }
 
-  private static getLanguageLabel (id: number) {
+  private static getLanguageLabel (id: string) {
     let languageLabel = VIDEO_LANGUAGES[id]
+    console.log(VIDEO_LANGUAGES)
+    console.log(id)
     if (!languageLabel) languageLabel = 'Unknown'
 
     return languageLabel
@@ -1083,7 +1085,7 @@ export class VideoModel extends Model<VideoModel> {
     let language
     if (this.language) {
       language = {
-        identifier: this.language + '',
+        identifier: this.language,
         name: VideoModel.getLanguageLabel(this.language)
       }
     }
index 1d19daa60b740becdd2b120ee824feca8935bea1..da41f515b7f6401f9e01c5cc58654185c4d2da48 100644 (file)
@@ -105,7 +105,7 @@ describe('Test videos API validator', function () {
         name: 'my super name',
         category: 5,
         licence: 1,
-        language: 6,
+        language: 'pt',
         nsfw: false,
         commentsEnabled: true,
         description: 'my super description',
@@ -151,7 +151,7 @@ describe('Test videos API validator', function () {
     })
 
     it('Should fail with a bad language', async function () {
-      const fields = immutableAssign(baseCorrectParams, { language: 125 })
+      const fields = immutableAssign(baseCorrectParams, { language: 'a'.repeat(15) })
       const attaches = baseCorrectAttaches
 
       await makeUploadRequest({ url: server.url, path: path + '/upload', token: server.accessToken, fields, attaches })
@@ -359,7 +359,7 @@ describe('Test videos API validator', function () {
       name: 'my super name',
       category: 5,
       licence: 2,
-      language: 6,
+      language: 'pt',
       nsfw: false,
       commentsEnabled: false,
       description: 'my super description',
@@ -413,7 +413,7 @@ describe('Test videos API validator', function () {
     })
 
     it('Should fail with a bad language', async function () {
-      const fields = immutableAssign(baseCorrectParams, { language: 125 })
+      const fields = immutableAssign(baseCorrectParams, { language: 'a'.repeat(15) })
 
       await makePutBodyRequest({ url: server.url, path: path + videoId, token: server.accessToken, fields })
     })
index 010b488d8baf572f739a57559d93e92ad99e7b0e..9d619a7ded3f9f8fae3490f8e5b6b935221065ef 100644 (file)
@@ -277,7 +277,7 @@ describe('Test follows', function () {
         name: 'server3-4',
         category: 2,
         licence: 6,
-        language: 3,
+        language: 'zh',
         nsfw: true,
         description: 'my super description',
         support: 'my super support text',
index f5ff3e9e52075fd406be4bcdf70c983740f9ef49..889825936bec6f6fbfbe9edccc7a0ae908cd6704 100644 (file)
@@ -32,7 +32,7 @@ describe('Test handle downs', function () {
     name: 'my super name for server 1',
     category: 5,
     licence: 4,
-    language: 9,
+    language: 'ja',
     nsfw: true,
     privacy: VideoPrivacy.PUBLIC,
     description: 'my super description for server 1',
@@ -49,7 +49,7 @@ describe('Test handle downs', function () {
     name: 'my super name for server 1',
     category: 5,
     licence: 4,
-    language: 9,
+    language: 'ja',
     nsfw: true,
     description: 'my super description for server 1',
     support: 'my super support text for server 1',
index e31c7febd5c9f2f466f8107ceae60235ebf97715..2563939ecdf4c24a5add56f22aacbdd9d6afe56b 100644 (file)
@@ -89,7 +89,7 @@ describe('Test multiple servers', function () {
         name: 'my super name for server 1',
         category: 5,
         licence: 4,
-        language: 9,
+        language: 'ja',
         nsfw: true,
         description: 'my super description for server 1',
         support: 'my super support text for server 1',
@@ -108,7 +108,7 @@ describe('Test multiple servers', function () {
           name: 'my super name for server 1',
           category: 5,
           licence: 4,
-          language: 9,
+          language: 'ja',
           nsfw: true,
           description: 'my super description for server 1',
           support: 'my super support text for server 1',
@@ -159,7 +159,7 @@ describe('Test multiple servers', function () {
         name: 'my super name for server 2',
         category: 4,
         licence: 3,
-        language: 11,
+        language: 'de',
         nsfw: true,
         description: 'my super description for server 2',
         support: 'my super support text for server 2',
@@ -180,7 +180,7 @@ describe('Test multiple servers', function () {
           name: 'my super name for server 2',
           category: 4,
           licence: 3,
-          language: 11,
+          language: 'de',
           nsfw: true,
           description: 'my super description for server 2',
           support: 'my super support text for server 2',
@@ -238,7 +238,7 @@ describe('Test multiple servers', function () {
         name: 'my super name for server 3',
         category: 6,
         licence: 5,
-        language: 11,
+        language: 'de',
         nsfw: true,
         description: 'my super description for server 3',
         support: 'my super support text for server 3',
@@ -251,7 +251,7 @@ describe('Test multiple servers', function () {
         name: 'my super name for server 3-2',
         category: 7,
         licence: 6,
-        language: 12,
+        language: 'ko',
         nsfw: false,
         description: 'my super description for server 3-2',
         support: 'my super support text for server 3-2',
@@ -286,7 +286,7 @@ describe('Test multiple servers', function () {
           name: 'my super name for server 3',
           category: 6,
           licence: 5,
-          language: 11,
+          language: 'de',
           nsfw: true,
           description: 'my super description for server 3',
           support: 'my super support text for server 3',
@@ -318,7 +318,7 @@ describe('Test multiple servers', function () {
           name: 'my super name for server 3-2',
           category: 7,
           licence: 6,
-          language: 12,
+          language: 'ko',
           nsfw: false,
           description: 'my super description for server 3-2',
           support: 'my super support text for server 3-2',
@@ -597,7 +597,7 @@ describe('Test multiple servers', function () {
         name: 'my super video updated',
         category: 10,
         licence: 7,
-        language: 13,
+        language: 'fr',
         nsfw: true,
         description: 'my super description updated',
         support: 'my super support text updated',
@@ -626,7 +626,7 @@ describe('Test multiple servers', function () {
           name: 'my super video updated',
           category: 10,
           licence: 7,
-          language: 13,
+          language: 'fr',
           nsfw: true,
           description: 'my super description updated',
           support: 'my super support text updated',
index 7c4bdf8bc888b6a0721bbc25cc2e56acfabac07c..5e163e9df005aa02a02f6d9219af27bf7de5da97 100644 (file)
@@ -23,7 +23,7 @@ describe('Test a single server', function () {
     name: 'my super name',
     category: 2,
     licence: 6,
-    language: 3,
+    language: 'zh',
     nsfw: true,
     description: 'my super description',
     support: 'my super support text',
@@ -54,7 +54,7 @@ describe('Test a single server', function () {
     name: 'my super video updated',
     category: 4,
     licence: 2,
-    language: 5,
+    language: 'ar',
     nsfw: false,
     description: 'my super description updated',
     support: 'my super support text updated',
@@ -115,7 +115,7 @@ describe('Test a single server', function () {
     const languages = res.body
     expect(Object.keys(languages)).to.have.length.above(5)
 
-    expect(languages[3]).to.equal('Mandarin')
+    expect(languages['ru']).to.equal('Russian')
   })
 
   it('Should list video privacies', async function () {
@@ -222,8 +222,8 @@ describe('Test a single server', function () {
   //   expect(video.categoryLabel).to.equal('Films')
   //   expect(video.licence).to.equal(6)
   //   expect(video.licenceLabel).to.equal('Attribution - Non Commercial - No Derivatives')
-  //   expect(video.language).to.equal(3)
-  //   expect(video.languageLabel).to.equal('Mandarin')
+  //   expect(video.language).to.equal('zh')
+  //   expect(video.languageLabel).to.equal('Chinese')
   //   expect(video.nsfw).to.be.ok
   //   expect(video.description).to.equal('my super description')
   //   expect(video.account.name).to.equal('root')
@@ -292,7 +292,7 @@ describe('Test a single server', function () {
         description: video + ' description',
         category: 2,
         licence: 1,
-        language: 1,
+        language: 'en',
         nsfw: true,
         tags: [ 'tag1', 'tag2', 'tag3' ],
         fixture: video
@@ -458,7 +458,7 @@ describe('Test a single server', function () {
       name: 'my super video updated',
       category: 4,
       licence: 2,
-      language: 5,
+      language: 'ar',
       nsfw: false,
       description: 'my super description updated',
       commentsEnabled: false,
index ae02ef64daa424f40b4b9d00676c1ba9adbf070a..b7375f77826a84fef48fa2cedfa643ebbda42295 100644 (file)
@@ -182,7 +182,7 @@ function upload (servers: ServerInfo[], numServer: number) {
     category: 4,
     nsfw: false,
     licence: 2,
-    language: 1,
+    language: 'en',
     description: Date.now() + ' description',
     tags: [ Date.now().toString().substring(0, 5) + 't1', Date.now().toString().substring(0, 5) + 't2' ],
     fixture: 'video_short1.webm'
index 5e186147e3e218223f1b18850608eab446612dc6..943c85cc73b2ac721adb46bcf04e304b138cdbd2 100644 (file)
@@ -24,7 +24,7 @@ type VideoAttributes = {
   name?: string
   category?: number
   licence?: number
-  language?: number
+  language?: string
   nsfw?: boolean
   commentsEnabled?: boolean
   description?: string
@@ -284,7 +284,7 @@ async function uploadVideo (url: string, accessToken: string, videoAttributesArg
     name: 'my super video',
     category: 5,
     licence: 4,
-    language: 3,
+    language: 'zh',
     channelId: defaultChannelId,
     nsfw: true,
     description: 'my super description',
@@ -403,7 +403,7 @@ async function completeVideoCheck (
     name: string
     category: number
     licence: number
-    language: number
+    language: string
     nsfw: boolean
     commentsEnabled: boolean
     description: string
@@ -437,11 +437,11 @@ async function completeVideoCheck (
 
   expect(video.name).to.equal(attributes.name)
   expect(video.category.id).to.equal(attributes.category)
-  expect(video.category.label).to.equal(VIDEO_CATEGORIES[attributes.category] || 'Misc')
+  expect(video.category.label).to.equal(attributes.category !== null ? VIDEO_CATEGORIES[attributes.category] : 'Misc')
   expect(video.licence.id).to.equal(attributes.licence)
-  expect(video.licence.label).to.equal(VIDEO_LICENCES[attributes.licence] || 'Unknown')
+  expect(video.licence.label).to.equal(attributes.licence !== null ? VIDEO_LICENCES[attributes.licence] : 'Unknown')
   expect(video.language.id).to.equal(attributes.language)
-  expect(video.language.label).to.equal(VIDEO_LANGUAGES[attributes.language] || 'Unknown')
+  expect(video.language.label).to.equal(attributes.language !== null ? VIDEO_LANGUAGES[attributes.language] : 'Unknown')
   expect(video.privacy.id).to.deep.equal(attributes.privacy)
   expect(video.privacy.label).to.deep.equal(VIDEO_PRIVACIES[attributes.privacy])
   expect(video.nsfw).to.equal(attributes.nsfw)
index e6272a433cfd988a31886774bbec1e62d58e4428..f773208abf128673504829840d9a6b67d273f359 100644 (file)
@@ -16,7 +16,7 @@ program
   .option('-U, --username <username>', 'Username')
   .option('-p, --password <token>', 'Password')
   .option('-t, --target-url <targetUrl>', 'Video target URL')
-  .option('-l, --language <languageCode>', 'Language code')
+  .option('-l, --language <languageCode>', 'Language ISO 639 code (fr or en...)')
   .option('-v, --verbose', 'Verbose mode')
   .parse(process.argv)
 
@@ -82,7 +82,7 @@ async function run () {
   })
 }
 
-function processVideo (info: any, languageCode: number) {
+function processVideo (info: any, languageCode: string) {
   return new Promise(async res => {
     if (program['verbose']) console.log('Fetching object.', info)
 
@@ -121,7 +121,7 @@ function processVideo (info: any, languageCode: number) {
   })
 }
 
-async function uploadVideoOnPeerTube (videoInfo: any, videoPath: string, language?: number) {
+async function uploadVideoOnPeerTube (videoInfo: any, videoPath: string, language?: string) {
   const category = await getCategory(videoInfo.categories)
   const licence = getLicence(videoInfo.license)
   let tags = []
index 765e9618a99fbdd4bad401950a0488443fee7d45..177d849f325b5ec1ce05d50d0d33a05e3a08765f 100644 (file)
@@ -18,7 +18,7 @@ program
   .option('-c, --category <category number>', 'Category number')
   .option('-m, --comments-enabled', 'Enable comments')
   .option('-l, --licence <licence number>', 'Licence number')
-  .option('-L, --language <language number>', 'Language number')
+  .option('-L, --language <language code>', 'Language ISO 639 code (fr or en...)')
   .option('-d, --video-description <description>', 'Video description')
   .option('-t, --tags <tags>', 'Video tags', list)
   .option('-b, --thumbnail <thumbnailPath>', 'Thumbnail path')
index 567a4c79a0d86591aa57c62f3bb7003f3561262c..562bc1bf2cc917439e50c1082d46679d390a5661 100644 (file)
@@ -3,7 +3,7 @@ import { VideoPrivacy } from './video-privacy.enum'
 export interface VideoCreate {
   category?: number
   licence?: number
-  language?: number
+  language?: string
   description?: string
   support?: string
   channelId: number
index b281ace9af0c9edc23df43ae8a54cafd090178f5..3a205bb83058c886b105c24d51681bbac94eed42 100644 (file)
@@ -4,7 +4,7 @@ export interface VideoUpdate {
   name?: string
   category?: number
   licence?: number
-  language?: number
+  language?: string
   description?: string
   support?: string
   privacy?: VideoPrivacy
index 70132c050988f2b13b6e97dd00fd9a7b07f4986d..259826689539e1ed88fb8982f4b7371f66b862a7 100644 (file)
@@ -5,7 +5,7 @@ import { VideoChannel } from './video-channel.model'
 import { VideoPrivacy } from './video-privacy.enum'
 
 export interface VideoConstant <T> {
-  id: number
+  id: T
   label: string
 }
 
@@ -25,7 +25,7 @@ export interface Video {
   publishedAt: Date | string
   category: VideoConstant<number>
   licence: VideoConstant<number>
-  language: VideoConstant<number>
+  language: VideoConstant<string>
   privacy: VideoConstant<VideoPrivacy>
   description: string
   duration: number
index 0729ac8ec97deadb4031720be26807feab77aa97..10f60175dd7b3b0dd84f0dfe7a8a0e97321e5fd0 100644 (file)
@@ -82,9 +82,9 @@ paths:
     get:
       tags:
         - Feeds
-      consumes:
-        - application/json
       produces:
+        - application/atom+xml
+        - application/rss+xml
         - application/json
       parameters:
         - name: format
@@ -107,9 +107,6 @@ paths:
       responses:
         '200':
           description: successful operation
-          content:
-            application/json:
-            application/xml:
   /jobs:
     get:
       security:
@@ -660,7 +657,7 @@ paths:
           description: 'Video licence'
         - name: language
           in: formData
-          type: number
+          type: string
           description: 'Video language'
         - name: description
           in: formData
@@ -804,7 +801,7 @@ paths:
           description: 'Video licence'
         - name: language
           in: formData
-          type: number
+          type: string
           description: 'Video language'
         - name: description
           in: formData
@@ -1245,12 +1242,18 @@ paths:
         '204':
           description: successful operation
 definitions:
-  VideoConstant:
+  VideoConstantNumber:
     properties:
       id:
         type: number
       label:
         type: string
+  VideoConstantString:
+    properties:
+      id:
+        type: string
+      label:
+        type: string
   VideoPrivacy:
     type: string
     enum: [Public, Unlisted, Private]
@@ -1267,11 +1270,11 @@ definitions:
       updatedAt:
         type: string
       category:
-        $ref: "#/definitions/VideoConstant"
+        $ref: "#/definitions/VideoConstantNumber"
       licence:
-        $ref: "#/definitions/VideoConstant"
+        $ref: "#/definitions/VideoConstantNumber"
       language:
-        $ref: "#/definitions/VideoConstant"
+        $ref: "#/definitions/VideoConstantString"
       privacy:
         $ref: "#/definitions/VideoPrivacy"
       description:
index 73488620ad02a112a277c3dcf7f139eda1228041..9a43aa182d24001835c724cc397ff9bb58b659c8 100644 (file)
--- a/yarn.lock
+++ b/yarn.lock
@@ -3239,6 +3239,10 @@ isexe@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
 
+iso-639-3@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/iso-639-3/-/iso-639-3-1.0.1.tgz#ebdf945e1e691bc8225e41e4520fe6a51083e647"
+
 isobject@^2.0.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89"