diff --git a/.tx/config b/.tx/config index d22492eedcd10363232c59e8f37072635501347a..6ca2251162e5ef7e275658c5f75a4859a1a92b2e 100644 --- a/.tx/config +++ b/.tx/config @@ -6,3 +6,9 @@ file_filter = translations/ring_client_windows_<lang>.ts source_file = translations/ring_client_windows.ts source_lang = en type = TS + +[jami.lrc_en_ts] +file_filter = translations/lrc_<lang>.ts +source_file = translations/lrc_en.ts +source_lang = en +type = TS diff --git a/CMakeLists.txt b/CMakeLists.txt index be5132a5525e05d6af9c2b863f5ea383931cb5b3..9e5ec8fcada28e625b8556432e3261f9ecabbad5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,16 +1,34 @@ -cmake_minimum_required(VERSION 3.11) - -if (APPLE) - project(Jami) +# Copyright (C) 2020-2022 Savoir-faire Linux Inc. +# +# Author: Albert Babà <albert.babi@savoirfairelinux.com> +# Author: Amin Bandali <amin.bandali@savoirfairelinux.com> +# Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> +# Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> +# Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com> +# Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +cmake_minimum_required(VERSION 3.16) + +if(APPLE) + project(Jami) else() - project(jami-qt) -endif() - -if(MSVC) - cmake_minimum_required(VERSION 3.15) + project(jami-qt) endif() -# todo: show error if Qt version < 5.14 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_FLAGS_DEBUG "-Og -ggdb") @@ -23,701 +41,698 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) # Here we let find_package(<PackageName>...) try to find Qt 6, # If it is found, find_package will succeed, and the CMake variable # QT_VERSION_MAJOR will be defined 6. -find_package(QT NAMES Qt6 REQUIRED) +if(QT6_VER AND QT6_PATH) + find_package(QT NAMES Qt6 REQUIRED + PATHS ${QT6_PATH} NO_DEFAULT_PATH) +else() + find_package(QT NAMES Qt6 REQUIRED) +endif() if (${QT_VERSION_MAJOR} STRLESS 6) - if (${QT_VERSION_MINOR} STRLESS 2) - message(FATAL_ERROR "Qt 6.2 or higher is required." ) - endif() + if (${QT_VERSION_MINOR} STRLESS 2) + message(FATAL_ERROR "Qt 6.2 or higher is required.") + endif() endif() + +# libjamiclient +set(LIBCLIENT_SRC_DIR ${PROJECT_SOURCE_DIR}/src/libclient) +add_subdirectory(${LIBCLIENT_SRC_DIR}) + set(QT_MODULES - Quick - Network - NetworkAuth - Svg - Gui - Qml - QmlModels - Sql - Concurrent - Core - Core5Compat - Multimedia - Widgets -) + Quick + Network + NetworkAuth + Svg + Gui + Qml + QmlModels + Sql + Concurrent + Core + Core5Compat + Multimedia + Widgets) if(NOT DEFINED WITH_WEBENGINE) - set(WITH_WEBENGINE true) + set(WITH_WEBENGINE true) endif() if(WITH_WEBENGINE) - list(APPEND QT_MODULES - WebEngineCore - WebEngineQuick - WebChannel - WebEngineWidgets - ) + list(APPEND QT_MODULES + WebEngineCore + WebEngineQuick + WebChannel + WebEngineWidgets) endif() -find_package(Qt6 COMPONENTS ${QT_MODULES} REQUIRED) -foreach(MODULE ${QT_MODULES}) - list(APPEND QT_LIBS "Qt::${MODULE}") -endforeach() - set(APP_SRC_DIR ${PROJECT_SOURCE_DIR}/src/app) -set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} ${Qt5Widgets_EXECUTABLE_COMPILE_FLAGS}) +set(CMAKE_CXX_FLAGS + ${CMAKE_CXX_FLAGS} ${Qt6Widgets_EXECUTABLE_COMPILE_FLAGS}) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH true) -if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.12.0") - include(FindPython3) - find_package (Python3 COMPONENTS Interpreter) - set(PYTHON_EXEC ${Python3_EXECUTABLE}) -else() - include(FindPythonInterp) - set(PYTHON_EXEC ${PYTHON_EXECUTABLE}) +# jami-daemon +set(CMAKE_MODULE_PATH + ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +find_package(LibJami REQUIRED) +if(LIBJAMI_FOUND) + include_directories(${LIBJAMI_INCLUDE_DIRS}) endif() +include(FindPython3) +find_package(Python3 COMPONENTS Interpreter) +set(PYTHON_EXEC ${Python3_EXECUTABLE}) + set(QML_RESOURCES ${PROJECT_SOURCE_DIR}/resources.qrc) if(WITH_WEBENGINE) - set(QML_RESOURCES_QML ${PROJECT_SOURCE_DIR}/qml.qrc) + set(QML_RESOURCES_QML ${PROJECT_SOURCE_DIR}/qml.qrc) else() - execute_process(COMMAND ${PYTHON_EXEC} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/gen-qrc-without-webengine.py - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) - set(QML_RESOURCES_QML ${PROJECT_SOURCE_DIR}/qml_without_webengine.qrc) + execute_process( + COMMAND + ${PYTHON_EXEC} ${CMAKE_CURRENT_SOURCE_DIR}/scripts/gen-qrc-without-webengine.py + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + set(QML_RESOURCES_QML + ${PROJECT_SOURCE_DIR}/qml_without_webengine.qrc) endif() if (APPLE) - include(FetchContent) - FetchContent_Declare( - libqrencode - GIT_REPOSITORY https://github.com/fukuchi/libqrencode.git - GIT_TAG v4.1.1 - ) - FetchContent_Populate(libqrencode) - add_subdirectory(${libqrencode_SOURCE_DIR} ${libqrencode_BINARY_DIR}) - include_directories(${libqrencode_SOURCE_DIR}) + include(FetchContent) + FetchContent_Declare( + libqrencode + GIT_REPOSITORY https://github.com/fukuchi/libqrencode.git + GIT_TAG v4.1.1) + FetchContent_Populate(libqrencode) + add_subdirectory(${libqrencode_SOURCE_DIR} ${libqrencode_BINARY_DIR}) + include_directories(${libqrencode_SOURCE_DIR}) endif() # Resource auto-gen -# check files in the resource directory and force a reconfigure if it changes +# check files in the resources directory and force a reconfigure if it +# changes file(GLOB_RECURSE - RES_FILES CONFIGURE_DEPENDS - ${PROJECT_SOURCE_DIR}/resources/* -) + RES_FILES CONFIGURE_DEPENDS + ${PROJECT_SOURCE_DIR}/resources/*) execute_process( - COMMAND ${PYTHON_EXEC} ${PROJECT_SOURCE_DIR}/gen-resources.py - WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} -) + COMMAND ${PYTHON_EXEC} ${PROJECT_SOURCE_DIR}/gen-resources.py + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) # library compatibility (boost, libnotify, etc.) add_definitions(-DQT_NO_KEYWORDS) set(COMMON_SOURCES - ${APP_SRC_DIR}/bannedlistmodel.cpp - ${APP_SRC_DIR}/accountlistmodel.cpp - ${APP_SRC_DIR}/networkmanager.cpp - ${APP_SRC_DIR}/instancemanager.cpp - ${APP_SRC_DIR}/main.cpp - ${APP_SRC_DIR}/smartlistmodel.cpp - ${APP_SRC_DIR}/utils.cpp - ${APP_SRC_DIR}/mainapplication.cpp - ${APP_SRC_DIR}/messagesadapter.cpp - ${APP_SRC_DIR}/accountadapter.cpp - ${APP_SRC_DIR}/calladapter.cpp - ${APP_SRC_DIR}/conversationsadapter.cpp - ${APP_SRC_DIR}/avadapter.cpp - ${APP_SRC_DIR}/contactadapter.cpp - ${APP_SRC_DIR}/pluginadapter.cpp - ${APP_SRC_DIR}/deviceitemlistmodel.cpp - ${APP_SRC_DIR}/pluginlistmodel.cpp - ${APP_SRC_DIR}/pluginhandlerlistmodel.cpp - ${APP_SRC_DIR}/preferenceitemlistmodel.cpp - ${APP_SRC_DIR}/mediacodeclistmodel.cpp - ${APP_SRC_DIR}/currentaccounttomigrate.cpp - ${APP_SRC_DIR}/audiodevicemodel.cpp - ${APP_SRC_DIR}/pluginlistpreferencemodel.cpp - ${APP_SRC_DIR}/audiomanagerlistmodel.cpp - ${APP_SRC_DIR}/qmlregister.cpp - ${APP_SRC_DIR}/utilsadapter.cpp - ${APP_SRC_DIR}/moderatorlistmodel.cpp - ${APP_SRC_DIR}/screensaver.cpp - ${APP_SRC_DIR}/systemtray.cpp - ${APP_SRC_DIR}/appsettingsmanager.cpp - ${APP_SRC_DIR}/lrcinstance.cpp - ${APP_SRC_DIR}/selectablelistproxymodel.cpp - ${APP_SRC_DIR}/conversationlistmodelbase.cpp - ${APP_SRC_DIR}/conversationlistmodel.cpp - ${APP_SRC_DIR}/searchresultslistmodel.cpp - ${APP_SRC_DIR}/calloverlaymodel.cpp - ${APP_SRC_DIR}/filestosendlistmodel.cpp - ${APP_SRC_DIR}/wizardviewstepmodel.cpp - ${APP_SRC_DIR}/avatarregistry.cpp - ${APP_SRC_DIR}/currentconversation.cpp - ${APP_SRC_DIR}/currentaccount.cpp - ${APP_SRC_DIR}/videodevices.cpp - ${APP_SRC_DIR}/videoprovider.cpp - ${APP_SRC_DIR}/callparticipantsmodel.cpp -) + ${APP_SRC_DIR}/bannedlistmodel.cpp + ${APP_SRC_DIR}/accountlistmodel.cpp + ${APP_SRC_DIR}/networkmanager.cpp + ${APP_SRC_DIR}/instancemanager.cpp + ${APP_SRC_DIR}/main.cpp + ${APP_SRC_DIR}/smartlistmodel.cpp + ${APP_SRC_DIR}/utils.cpp + ${APP_SRC_DIR}/mainapplication.cpp + ${APP_SRC_DIR}/messagesadapter.cpp + ${APP_SRC_DIR}/accountadapter.cpp + ${APP_SRC_DIR}/calladapter.cpp + ${APP_SRC_DIR}/conversationsadapter.cpp + ${APP_SRC_DIR}/avadapter.cpp + ${APP_SRC_DIR}/contactadapter.cpp + ${APP_SRC_DIR}/pluginadapter.cpp + ${APP_SRC_DIR}/deviceitemlistmodel.cpp + ${APP_SRC_DIR}/pluginlistmodel.cpp + ${APP_SRC_DIR}/pluginhandlerlistmodel.cpp + ${APP_SRC_DIR}/preferenceitemlistmodel.cpp + ${APP_SRC_DIR}/mediacodeclistmodel.cpp + ${APP_SRC_DIR}/currentaccounttomigrate.cpp + ${APP_SRC_DIR}/audiodevicemodel.cpp + ${APP_SRC_DIR}/pluginlistpreferencemodel.cpp + ${APP_SRC_DIR}/audiomanagerlistmodel.cpp + ${APP_SRC_DIR}/qmlregister.cpp + ${APP_SRC_DIR}/utilsadapter.cpp + ${APP_SRC_DIR}/moderatorlistmodel.cpp + ${APP_SRC_DIR}/screensaver.cpp + ${APP_SRC_DIR}/systemtray.cpp + ${APP_SRC_DIR}/appsettingsmanager.cpp + ${APP_SRC_DIR}/lrcinstance.cpp + ${APP_SRC_DIR}/selectablelistproxymodel.cpp + ${APP_SRC_DIR}/conversationlistmodelbase.cpp + ${APP_SRC_DIR}/conversationlistmodel.cpp + ${APP_SRC_DIR}/searchresultslistmodel.cpp + ${APP_SRC_DIR}/calloverlaymodel.cpp + ${APP_SRC_DIR}/filestosendlistmodel.cpp + ${APP_SRC_DIR}/wizardviewstepmodel.cpp + ${APP_SRC_DIR}/avatarregistry.cpp + ${APP_SRC_DIR}/currentconversation.cpp + ${APP_SRC_DIR}/currentaccount.cpp + ${APP_SRC_DIR}/videodevices.cpp + ${APP_SRC_DIR}/videoprovider.cpp + ${APP_SRC_DIR}/callparticipantsmodel.cpp) set(COMMON_HEADERS - ${APP_SRC_DIR}/avatarimageprovider.h - ${APP_SRC_DIR}/networkmanager.h - ${APP_SRC_DIR}/smartlistmodel.h - ${APP_SRC_DIR}/updatemanager.h - ${APP_SRC_DIR}/utils.h - ${APP_SRC_DIR}/bannedlistmodel.h - ${APP_SRC_DIR}/version.h - ${APP_SRC_DIR}/accountlistmodel.h - ${APP_SRC_DIR}/instancemanager.h - ${APP_SRC_DIR}/connectivitymonitor.h - ${APP_SRC_DIR}/jamiavatartheme.h - ${APP_SRC_DIR}/mainapplication.h - ${APP_SRC_DIR}/qrimageprovider.h - ${APP_SRC_DIR}/messagesadapter.h - ${APP_SRC_DIR}/accountadapter.h - ${APP_SRC_DIR}/calladapter.h - ${APP_SRC_DIR}/conversationsadapter.h - ${APP_SRC_DIR}/qmladapterbase.h - ${APP_SRC_DIR}/avadapter.h - ${APP_SRC_DIR}/contactadapter.h - ${APP_SRC_DIR}/pluginadapter.h - ${APP_SRC_DIR}/deviceitemlistmodel.h - ${APP_SRC_DIR}/pluginlistmodel.h - ${APP_SRC_DIR}/pluginhandlerlistmodel.h - ${APP_SRC_DIR}/preferenceitemlistmodel.h - ${APP_SRC_DIR}/mediacodeclistmodel.h - ${APP_SRC_DIR}/currentaccounttomigrate.h - ${APP_SRC_DIR}/audiodevicemodel.h - ${APP_SRC_DIR}/pluginlistpreferencemodel.h - ${APP_SRC_DIR}/audiomanagerlistmodel.h - ${APP_SRC_DIR}/qmlregister.h - ${APP_SRC_DIR}/abstractlistmodelbase.h - ${APP_SRC_DIR}/quickimageproviderbase.h - ${APP_SRC_DIR}/qtutils.h - ${APP_SRC_DIR}/utilsadapter.h - ${APP_SRC_DIR}/moderatorlistmodel.h - ${APP_SRC_DIR}/screensaver.h - ${APP_SRC_DIR}/systemtray.h - ${APP_SRC_DIR}/appsettingsmanager.h - ${APP_SRC_DIR}/lrcinstance.h - ${APP_SRC_DIR}/selectablelistproxymodel.h - ${APP_SRC_DIR}/conversationlistmodelbase.h - ${APP_SRC_DIR}/conversationlistmodel.h - ${APP_SRC_DIR}/searchresultslistmodel.h - ${APP_SRC_DIR}/calloverlaymodel.h - ${APP_SRC_DIR}/filestosendlistmodel.h - ${APP_SRC_DIR}/wizardviewstepmodel.h - ${APP_SRC_DIR}/avatarregistry.h - ${APP_SRC_DIR}/currentconversation.h - ${APP_SRC_DIR}/currentaccount.h - ${APP_SRC_DIR}/videodevices.h - ${APP_SRC_DIR}/videoprovider.h - ${APP_SRC_DIR}/callparticipantsmodel.h -) + ${APP_SRC_DIR}/avatarimageprovider.h + ${APP_SRC_DIR}/networkmanager.h + ${APP_SRC_DIR}/smartlistmodel.h + ${APP_SRC_DIR}/updatemanager.h + ${APP_SRC_DIR}/utils.h + ${APP_SRC_DIR}/bannedlistmodel.h + ${APP_SRC_DIR}/version.h + ${APP_SRC_DIR}/accountlistmodel.h + ${APP_SRC_DIR}/instancemanager.h + ${APP_SRC_DIR}/connectivitymonitor.h + ${APP_SRC_DIR}/jamiavatartheme.h + ${APP_SRC_DIR}/mainapplication.h + ${APP_SRC_DIR}/qrimageprovider.h + ${APP_SRC_DIR}/messagesadapter.h + ${APP_SRC_DIR}/accountadapter.h + ${APP_SRC_DIR}/calladapter.h + ${APP_SRC_DIR}/conversationsadapter.h + ${APP_SRC_DIR}/qmladapterbase.h + ${APP_SRC_DIR}/avadapter.h + ${APP_SRC_DIR}/contactadapter.h + ${APP_SRC_DIR}/pluginadapter.h + ${APP_SRC_DIR}/deviceitemlistmodel.h + ${APP_SRC_DIR}/pluginlistmodel.h + ${APP_SRC_DIR}/pluginhandlerlistmodel.h + ${APP_SRC_DIR}/preferenceitemlistmodel.h + ${APP_SRC_DIR}/mediacodeclistmodel.h + ${APP_SRC_DIR}/currentaccounttomigrate.h + ${APP_SRC_DIR}/audiodevicemodel.h + ${APP_SRC_DIR}/pluginlistpreferencemodel.h + ${APP_SRC_DIR}/audiomanagerlistmodel.h + ${APP_SRC_DIR}/qmlregister.h + ${APP_SRC_DIR}/abstractlistmodelbase.h + ${APP_SRC_DIR}/quickimageproviderbase.h + ${APP_SRC_DIR}/qtutils.h + ${APP_SRC_DIR}/utilsadapter.h + ${APP_SRC_DIR}/moderatorlistmodel.h + ${APP_SRC_DIR}/screensaver.h + ${APP_SRC_DIR}/systemtray.h + ${APP_SRC_DIR}/appsettingsmanager.h + ${APP_SRC_DIR}/lrcinstance.h + ${APP_SRC_DIR}/selectablelistproxymodel.h + ${APP_SRC_DIR}/conversationlistmodelbase.h + ${APP_SRC_DIR}/conversationlistmodel.h + ${APP_SRC_DIR}/searchresultslistmodel.h + ${APP_SRC_DIR}/calloverlaymodel.h + ${APP_SRC_DIR}/filestosendlistmodel.h + ${APP_SRC_DIR}/wizardviewstepmodel.h + ${APP_SRC_DIR}/avatarregistry.h + ${APP_SRC_DIR}/currentconversation.h + ${APP_SRC_DIR}/currentaccount.h + ${APP_SRC_DIR}/videodevices.h + ${APP_SRC_DIR}/videoprovider.h + ${APP_SRC_DIR}/callparticipantsmodel.h) if(WITH_WEBENGINE) - list(APPEND COMMON_SOURCES - ${APP_SRC_DIR}/previewengine.cpp) - add_definitions(-DWITH_WEBENGINE) + list(APPEND COMMON_SOURCES + ${APP_SRC_DIR}/previewengine.cpp) + add_definitions(-DWITH_WEBENGINE) else() - list(APPEND COMMON_SOURCES - ${APP_SRC_DIR}/nowebengine/previewengine.cpp) + list(APPEND COMMON_SOURCES + ${APP_SRC_DIR}/nowebengine/previewengine.cpp) endif() # For libavutil/avframe. set(LIBJAMI_CONTRIB_DIR "${PROJECT_SOURCE_DIR}/../daemon/contrib") find_path(AVUTIL_INCLUDE_DIR libavutil/avutil.h - PATHS - ${LIBJAMI_CONTRIB_DIR}/native/ffmpeg - ${LIBJAMI_CONTRIB_DIR}/build/ffmpeg/Build/win32/x64/include) + PATHS + ${LIBJAMI_CONTRIB_DIR}/native/ffmpeg + ${LIBJAMI_CONTRIB_DIR}/build/ffmpeg/Build/win32/x64/include) include_directories(${AVUTIL_INCLUDE_DIR}) find_package(Vulkan) if(Vulkan_FOUND) - add_definitions(-DHAS_VULKAN) - include_directories(${Vulkan_INCLUDE_DIR}) + add_definitions(-DHAS_VULKAN) + include_directories(${Vulkan_INCLUDE_DIR}) endif() if(MSVC) - set(WINDOWS_SYS_LIBS - Shell32.lib - Ole32.lib - Advapi32.lib - Shlwapi.lib - User32.lib - Gdi32.lib - Crypt32.lib - Strmiids.lib - ) - - list(APPEND COMMON_SOURCES - ${APP_SRC_DIR}/connectivitymonitor.cpp - ${APP_SRC_DIR}/updatemanager.cpp - ) - # preprocessor defines - add_definitions(-DUNICODE -DQT_NO_DEBUG -DNDEBUG) - - # dependencies - set(LRC ${PROJECT_SOURCE_DIR}/../lrc) - set(DRING ${PROJECT_SOURCE_DIR}/../daemon) - set(QRENCODE_DIR ${PROJECT_SOURCE_DIR}/3rdparty/qrencode-win32/qrencode-win32) - - # compiler options - add_compile_options(/wd4068 /wd4099 /wd4189 /wd4267 /wd4577 /wd4467 /wd4715 /wd4828) - add_compile_options(/MP /GS /W3 /Gy /Zc:wchar_t /Zi /Gm- /O2 /Zc:inline /fp:precise) - add_compile_options(/Gd /Oi /MD /FC /EHsc /nologo /sdl) - - # linker options - add_link_options( - "/IGNORE:4006,4049,4078,4098" - "/FORCE:MULTIPLE" - "/INCREMENTAL:NO" - "/DEBUG" - "/LTCG" - "/NODEFAULTLIB:LIBCMT" - ) - - # client deps - set(QRENCODE_LIB ${QRENCODE_DIR}/vc8/qrcodelib/x64/Release-Lib/qrcodelib.lib) - - # lrc - set(LRC_SRC_PATH ${LRC}/src) - set(RINGCLIENT_STATIC_LIB ${LRC}/build/release/ringclient_static.lib) - set(QTWRAPPER_LIB ${LRC}/build/src/qtwrapper/Release/qtwrapper.lib) - - # daemon - set(DRING_SRC_PATH ${DRING}/contrib/msvc/include) - set(DRING_LIB ${DRING}/build/x64/ReleaseLib_win32/bin/jami.lib) - set(GNUTLS_LIB ${DRING}/contrib/msvc/lib/x64/libgnutls.lib) - - # Beta config - if(BETA) - message(STATUS "Beta config enabled") - add_definitions(-DBETA) - set(JAMI_OUTPUT_DIRECTORY_RELEASE ${PROJECT_SOURCE_DIR}/x64/Beta) - else() - set(JAMI_OUTPUT_DIRECTORY_RELEASE ${PROJECT_SOURCE_DIR}/x64/Release) - endif() - - include_directories( - ${DRING_SRC_PATH} - ${LRC_SRC_PATH} - ${QRENCODE_DIR} - ) + set(WINDOWS_SYS_LIBS + Shell32.lib + Ole32.lib + Advapi32.lib + Shlwapi.lib + User32.lib + Gdi32.lib + Crypt32.lib + Strmiids.lib) + + list(APPEND COMMON_SOURCES + ${APP_SRC_DIR}/connectivitymonitor.cpp + ${APP_SRC_DIR}/updatemanager.cpp) + # preprocessor defines + add_definitions(-DUNICODE -DQT_NO_DEBUG -DNDEBUG) + + # dependencies + set(DRING ${PROJECT_SOURCE_DIR}/../daemon) + set(QRENCODE_DIR + ${PROJECT_SOURCE_DIR}/3rdparty/qrencode-win32/qrencode-win32) + + # compiler options + add_compile_options( + /wd4068 /wd4099 /wd4189 /wd4267 /wd4577 /wd4467 /wd4715 /wd4828) + add_compile_options( + /MP /GS /W3 /Gy /Zc:wchar_t /Zi /Gm- /O2 /Zc:inline /fp:precise) + add_compile_options(/Gd /Oi /MD /FC /EHsc /nologo /sdl) + + # linker options + add_link_options( + "/IGNORE:4006,4049,4078,4098" + "/FORCE:MULTIPLE" + "/INCREMENTAL:NO" + "/DEBUG" + "/LTCG" + "/NODEFAULTLIB:LIBCMT") + + # client deps + set(QRENCODE_LIB + ${QRENCODE_DIR}/vc8/qrcodelib/x64/Release-Lib/qrcodelib.lib) + + # libjamiclient + set(LIBCLIENT_STATIC_LIB + ${PROJECT_SOURCE_DIR}/build/release/${LIBCLIENT_NAME}.lib) + set(QTWRAPPER_LIB + ${PROJECT_SOURCE_DIR}/build/src/qtwrapper/Release/qtwrapper.lib) + + # daemon + set(DRING_SRC_PATH ${DRING}/contrib/msvc/include) + set(DRING_LIB ${DRING}/build/x64/ReleaseLib_win32/bin/jami.lib) + set(GNUTLS_LIB ${DRING}/contrib/msvc/lib/x64/libgnutls.lib) + + # Beta config + if(BETA) + message(STATUS "Beta config enabled") + add_definitions(-DBETA) + set(JAMI_OUTPUT_DIRECTORY_RELEASE ${PROJECT_SOURCE_DIR}/x64/Beta) + else() + set(JAMI_OUTPUT_DIRECTORY_RELEASE + ${PROJECT_SOURCE_DIR}/x64/Release) + endif() + + include_directories( + ${DRING_SRC_PATH} + ${LIBCLIENT_SRC_DIR} + ${QRENCODE_DIR}) elseif (NOT APPLE) - list(APPEND COMMON_SOURCES - ${APP_SRC_DIR}/xrectsel.c - ${APP_SRC_DIR}/dbuserrorhandler.cpp - ${APP_SRC_DIR}/connectivitymonitor.cpp - ${APP_SRC_DIR}/updatemanager.cpp) - list(APPEND COMMON_HEADERS - ${APP_SRC_DIR}/dbuserrorhandler.h - ${APP_SRC_DIR}/xrectsel.h) - list(APPEND QT_LIBS Qt::DBus) - list(APPEND QT_MODULES DBus) - - find_package(PkgConfig REQUIRED) - - pkg_check_modules(GLIB REQUIRED glib-2.0) - if(GLIB_FOUND) - add_definitions(${GLIB_CFLAGS_OTHER}) - endif() - - pkg_check_modules(GIO REQUIRED gio-2.0) - if(GIO_FOUND) - add_definitions(${GIO_CFLAGS}) - endif() - - pkg_check_modules(LIBNM libnm) - if(LIBNM_FOUND) - add_definitions(-DUSE_LIBNM) - endif() - - pkg_check_modules(LIBNOTIFY libnotify>=0.7.6) - if(LIBNOTIFY_FOUND) - add_definitions(-DUSE_LIBNOTIFY) - add_definitions(${LIBNOTIFY_CFLAGS}) - pkg_check_modules(LIBGDKPIXBUF gdk-pixbuf-2.0>=2.40.0) - add_definitions(${LIBGDKPIXBUF_CFLAGS}) - endif() - - if(NOT DEFINED LRC) - if(EXISTS ${PROJECT_SOURCE_DIR}/../install/lrc) - set(LRC ${PROJECT_SOURCE_DIR}/../install/lrc) - endif() - endif() - - # If LRC is not globally installed, it's path should be specified - # by setting variable LRC. If library is not inside LRC + suffixes - # lib, build or build-local, it's path should be set with LRCLIB. - if(DEFINED LRC) - if(EXISTS ${LRC}/include/libringclient) - set(LRC_SRC_PATH ${LRC}/include/libringclient) - else() - set(LRC_SRC_PATH ${LRC}/src) - endif() - if(NOT DEFINED LRCLIB) - set(LRCLIB ${LRC}) - endif() - find_library(ringclient ringclient - PATHS ${LRCLIB} - PATH_SUFFIXES lib build build-local NO_DEFAULT_PATH) - message("Will expect lrc library in ${LRCLIB} (including \ - subdirs /lib, /build and /build-local)") - set(LRC_LIB_NAME ${ringclient}) - else() - find_package(LibRingClient REQUIRED) - if (LibRingClient_FOUND) - set(LRC_SRC_PATH ${LIB_RING_CLIENT_INCLUDE_DIR}) - set(LRC_LIB_NAME ${LIB_RING_CLIENT_LIBRARY}) - else() - message("lrc not found!") - endif() - endif() - - message("Will expect lrc headers in ${LRC_SRC_PATH}") - - include_directories(${LRC_SRC_PATH} - ${LIBNM_INCLUDE_DIRS} - ${LIBNOTIFY_INCLUDE_DIRS} - ${LIBGDKPIXBUF_INCLUDE_DIRS} - ${GLIB_INCLUDE_DIRS}) - - set(JAMI_DATA_PREFIX "${CMAKE_INSTALL_PREFIX}/share") - - find_library(ringclient ringclient ${LRCLIBDIR} NO_DEFAULT_PATH) - find_library(qrencode qrencode) - find_library(X11 X11) + list(APPEND COMMON_SOURCES + ${APP_SRC_DIR}/xrectsel.c + ${APP_SRC_DIR}/connectivitymonitor.cpp + ${APP_SRC_DIR}/dbuserrorhandler.cpp + ${APP_SRC_DIR}/updatemanager.cpp) + list(APPEND COMMON_HEADERS + ${APP_SRC_DIR}/xrectsel.h + ${APP_SRC_DIR}/dbuserrorhandler.h) + list(APPEND QT_MODULES DBus) + + find_package(PkgConfig REQUIRED) + + pkg_check_modules(GLIB REQUIRED glib-2.0) + if(GLIB_FOUND) + add_definitions(${GLIB_CFLAGS_OTHER}) + endif() + + pkg_check_modules(GIO REQUIRED gio-2.0) + if(GIO_FOUND) + add_definitions(${GIO_CFLAGS}) + endif() + + pkg_check_modules(LIBNM libnm) + if(LIBNM_FOUND) + add_definitions(-DUSE_LIBNM) + endif() + + pkg_check_modules(LIBNOTIFY libnotify>=0.7.6) + if(LIBNOTIFY_FOUND) + add_definitions(-DUSE_LIBNOTIFY) + add_definitions(${LIBNOTIFY_CFLAGS}) + pkg_check_modules(LIBGDKPIXBUF gdk-pixbuf-2.0>=2.40.0) + add_definitions(${LIBGDKPIXBUF_CFLAGS}) + endif() + + pkg_check_modules(XCB xcb) + + include_directories( + ${LIBCLIENT_SRC_DIR} + ${LIBNM_INCLUDE_DIRS} + ${LIBNOTIFY_INCLUDE_DIRS} + ${LIBGDKPIXBUF_INCLUDE_DIRS} + ${GLIB_INCLUDE_DIRS} + ${XCB_INCLUDE_DIRS}) + + set(JAMI_DATA_PREFIX "${CMAKE_INSTALL_PREFIX}/share") + + find_library(${LIBCLIENT_NAME} ${LIBCLIENT_NAME} NO_DEFAULT_PATH) + find_library(qrencode qrencode) + find_library(X11 X11) else() # APPLE - list(APPEND COMMON_SOURCES - ${APP_SRC_DIR}/os/macos/updatemanager.mm - ${APP_SRC_DIR}/os/macos/connectivitymonitor.mm - ${APP_SRC_DIR}/os/macos/macutils.mm) - list(APPEND COMMON_HEADERS - ${APP_SRC_DIR}/os/macos/macutils.h) - if(NOT DEFINED LRC) - if(EXISTS ${PROJECT_SOURCE_DIR}/../install/lrc) - set(LRC ${PROJECT_SOURCE_DIR}/../install/lrc) - endif() - endif() - if(DEFINED LRC) - if(EXISTS ${LRC}/include/libringclient) - set(LRC_SRC_PATH ${LRC}/include/libringclient) - else() - set(LRC_SRC_PATH ${LRC}/src) - endif() - if(NOT DEFINED LRCLIB) - set(LRCLIB ${LRC}) - endif() - find_library(ringclient ringclient - PATHS ${LRCLIB} - PATH_SUFFIXES lib build build-local NO_DEFAULT_PATH) - set(LRC_LIB_NAME ${ringclient}) - else() - find_package(LibRingClient REQUIRED) - if (LibRingClient_FOUND) - set(LRC_SRC_PATH ${LIB_RING_CLIENT_INCLUDE_DIR}) - set(LRC_LIB_NAME ${LIB_RING_CLIENT_LIBRARY}) - else() - message("lrc not found!") - endif() - endif() - - message("Will expect lrc headers in ${LRC_SRC_PATH}") - - include_directories(${LRC_SRC_PATH}) - - set(JAMI_DATA_PREFIX "${CMAKE_INSTALL_PREFIX}/share") - - find_library(ringclient ringclient ${LRCLIBDIR} NO_DEFAULT_PATH) - find_library(SYSTEM_CONFIGURATUION SystemConfiguration) - set(myApp_ICON ${CMAKE_CURRENT_SOURCE_DIR}/resources/images/jami.icns) - set_source_files_properties(${myApp_ICON} PROPERTIES - MACOSX_PACKAGE_LOCATION Resources) - if(ENABLE_SPARKLE) - message("Sparkle auto-update enabled") - find_library(SPARKLE_FRAMEWORK - NAMES Sparkle - HINTS ${CMAKE_CURRENT_SOURCE_DIR}/sparkle) - add_definitions(-DENABLE_SPARKLE) - message("Sparkle is here:" ${SPARKLE_FRAMEWORK}) - set(PUBLIC_KEY_PATH "${CMAKE_CURRENT_SOURCE_DIR}/sparkle/dsa_pub.pem") - set_source_files_properties(${PUBLIC_KEY_PATH} PROPERTIES MACOSX_PACKAGE_LOCATION Resources) - set(PUBLIC_KEY ${PUBLIC_KEY_PATH}) - endif() - if(BETA) - message(STATUS "Beta config enabled") - add_definitions(-DBETA) - endif() + list(APPEND COMMON_SOURCES + ${APP_SRC_DIR}/os/macos/updatemanager.mm + ${APP_SRC_DIR}/os/macos/connectivitymonitor.mm + ${APP_SRC_DIR}/os/macos/macutils.mm) + list(APPEND COMMON_HEADERS + ${APP_SRC_DIR}/os/macos/macutils.h) + include_directories(${LIBCLIENT_SRC_DIR}) + + set(JAMI_DATA_PREFIX "${CMAKE_INSTALL_PREFIX}/share") + + find_library(SYSTEM_CONFIGURATUION SystemConfiguration) + set(myApp_ICON + ${CMAKE_CURRENT_SOURCE_DIR}/resources/images/jami.icns) + set_source_files_properties( + ${myApp_ICON} + PROPERTIES + MACOSX_PACKAGE_LOCATION Resources) + if(ENABLE_SPARKLE) + message("Sparkle auto-update enabled") + find_library(SPARKLE_FRAMEWORK + NAMES Sparkle + HINTS ${CMAKE_CURRENT_SOURCE_DIR}/sparkle) + add_definitions(-DENABLE_SPARKLE) + message("Sparkle is here:" ${SPARKLE_FRAMEWORK}) + set(PUBLIC_KEY_PATH + "${CMAKE_CURRENT_SOURCE_DIR}/sparkle/dsa_pub.pem") + set_source_files_properties( + ${PUBLIC_KEY_PATH} + PROPERTIES + MACOSX_PACKAGE_LOCATION Resources) + set(PUBLIC_KEY ${PUBLIC_KEY_PATH}) + endif() + if(BETA) + message(STATUS "Beta config enabled") + add_definitions(-DBETA) + endif() endif() # Qt find package if(QT6_VER AND QT6_PATH) - message(STATUS "Using custom Qt version") - find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS ${QT_MODULES} - PATHS ${QT6_PATH} NO_DEFAULT_PATH) - # Linguist tools is not required. - find_package(Qt${QT_VERSION_MAJOR} COMPONENTS LinguistTools - PATHS ${QT6_PATH} NO_DEFAULT_PATH) + message(STATUS "Using custom Qt version") + find_package(Qt${QT_VERSION_MAJOR} + REQUIRED COMPONENTS ${QT_MODULES} + OPTIONAL_COMPONENTS LinguistTools + PATHS ${QT6_PATH} NO_DEFAULT_PATH) else() - find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS ${QT_MODULES}) - find_package(Qt${QT_VERSION_MAJOR}LinguistTools) + find_package(Qt${QT_VERSION_MAJOR} + REQUIRED COMPONENTS ${QT_MODULES} + OPTIONAL_COMPONENTS LinguistTools) endif() -# common include -include_directories(${PROJECT_SOURCE_DIR} - ${APP_SRC_DIR}) +# common includes +include_directories( + ${PROJECT_SOURCE_DIR} + ${APP_SRC_DIR}) + +if(ENABLE_LIBWRAP) + list(APPEND COMMON_HEADERS + ${LIBCLIENT_SRC_DIR}/qtwrapper/instancemanager_wrap.h) +endif() # common executable sources -qt_add_executable(${PROJECT_NAME} MANUAL_FINALIZATION - ${APP_SRC_DIR}/main.cpp - ${COMMON_HEADERS} - ${COMMON_SOURCES} - ${QML_RESOURCES} - ${QML_RESOURCES_QML} - ${LRC_SRC_PATH}/webresource.qrc) +qt_add_executable( + ${PROJECT_NAME} + MANUAL_FINALIZATION + ${APP_SRC_DIR}/main.cpp + ${COMMON_HEADERS} + ${COMMON_SOURCES} + ${QML_RESOURCES} + ${QML_RESOURCES_QML} + ${LIBCLIENT_SRC_DIR}/webresource.qrc) + +foreach(MODULE ${QT_MODULES}) + list(APPEND QT_LIBS "Qt::${MODULE}") +endforeach() if(MSVC) - # Makes it a GUI executable instead of a console application - set_target_properties(${PROJECT_NAME} PROPERTIES WIN32_EXECUTABLE TRUE) - - target_link_libraries(${PROJECT_NAME} PRIVATE - ${QT_LIBS} - ${QRENCODE_LIB} - ${WINDOWS_SYS_LIBS}) - - # specify output executable files - set_target_properties(${PROJECT_NAME} - PROPERTIES - RUNTIME_OUTPUT_DIRECTORY_RELEASE "${JAMI_OUTPUT_DIRECTORY_RELEASE}" - ) - - # executable icon - target_sources(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/ico.rc) - - target_link_libraries(${PROJECT_NAME} PRIVATE - ${RINGCLIENT_STATIC_LIB} - ${QTWRAPPER_LIB} - ${DRING_LIB} - ${GNUTLS_LIB}) - - # translations - if(Qt${QT_VERSION_MAJOR}LinguistTools_FOUND) - message("Releasing and copying translation files") - file(MAKE_DIRECTORY "${JAMI_OUTPUT_DIRECTORY_RELEASE}/share/ring/translations/") - file(MAKE_DIRECTORY "${JAMI_OUTPUT_DIRECTORY_RELEASE}/share/libringclient/translations/") - file(GLOB TS_CLIENT_FILES ${PROJECT_SOURCE_DIR}/translations/*.ts) - file(GLOB TS_LRC_FILES ${LRC}/translations/*.ts) - set_source_files_properties(${TS_CLIENT_FILES} PROPERTIES OUTPUT_LOCATION - "${JAMI_OUTPUT_DIRECTORY_RELEASE}/share/ring/translations") - set_source_files_properties(${TS_LRC_FILES} PROPERTIES OUTPUT_LOCATION - "${JAMI_OUTPUT_DIRECTORY_RELEASE}/share/libringclient/translations") - - qt_add_translation(QM_CLIENT_FILES ${TS_CLIENT_FILES}) - qt_add_translation(QM_LRC_FILES ${TS_LRC_FILES}) - target_sources(${PROJECT_NAME} PRIVATE ${QM_CLIENT_FILES}) - target_sources(${PROJECT_NAME} PRIVATE ${QM_LRC_FILES}) - endif() - - # POST_BUILD steps - - # check time stamp - set(TIME_STAMP_FILE ".deploy.stamp") - add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - WORKING_DIRECTORY "$<TARGET_FILE_DIR:${PROJECT_NAME}>" - COMMAND ${CMAKE_COMMAND} -DTIME_STAMP_FILE=${TIME_STAMP_FILE} - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/time_stamp_check.cmake) - - # copy runtime files and run windeployqt on target and deploy Qt libs - add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - WORKING_DIRECTORY "$<TARGET_FILE_DIR:${PROJECT_NAME}>" - COMMAND ${CMAKE_COMMAND} -DTIME_STAMP_FILE=${TIME_STAMP_FILE} - -DCOPY_TO_PATH=$<TARGET_FILE_DIR:${PROJECT_NAME}> - -DDRING_PATH=${DRING} - -DPROJECT_ROOT_DIR=${PROJECT_SOURCE_DIR} - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/windows_daemon_deploy.cmake) - - add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - WORKING_DIRECTORY "$<TARGET_FILE_DIR:${PROJECT_NAME}>" - COMMAND ${CMAKE_COMMAND} -DTIME_STAMP_FILE=${TIME_STAMP_FILE} - -DWIN_DEPLOY_QT_PATH=${CMAKE_PREFIX_PATH}/bin - -DQML_SRC_DIR=${APP_SRC_DIR} - -DEXE_NAME=$<TARGET_FILE:${PROJECT_NAME}> - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/windows_qt_deploy.cmake) - - # create time stamp - add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - WORKING_DIRECTORY "$<TARGET_FILE_DIR:${PROJECT_NAME}>" - COMMAND ${CMAKE_COMMAND} -DTIME_STAMP_FILE=${TIME_STAMP_FILE} - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/time_stamp_create.cmake) - - # executable name - set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "Jami") + # Makes it a GUI executable instead of a console application + set_target_properties( + ${PROJECT_NAME} + PROPERTIES + WIN32_EXECUTABLE TRUE) + + target_link_libraries( + ${PROJECT_NAME} + PRIVATE + ${DRING_LIB} + ${GNUTLS_LIB} + ${LIBCLIENT_STATIC_LIB} + ${QTWRAPPER_LIB} + ${QT_LIBS} + ${QRENCODE_LIB} + ${WINDOWS_SYS_LIBS}) + + # specify output executable files + set_target_properties( + ${PROJECT_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY_RELEASE + "${JAMI_OUTPUT_DIRECTORY_RELEASE}") + + # executable icon + target_sources(${PROJECT_NAME} PRIVATE ${PROJECT_SOURCE_DIR}/ico.rc) + + # translations + if(Qt${QT_VERSION_MAJOR}LinguistTools_FOUND) + message("Releasing and copying translation files") + file(MAKE_DIRECTORY + "${JAMI_OUTPUT_DIRECTORY_RELEASE}/share/jami/translations/") + file(GLOB TS_FILES ${PROJECT_SOURCE_DIR}/translations/*.ts) + set_source_files_properties( + ${TS_FILES} + PROPERTIES + OUTPUT_LOCATION + "${JAMI_OUTPUT_DIRECTORY_RELEASE}/share/jami/translations") + + qt_add_translation(QM_FILES ${TS_FILES}) + target_sources(${PROJECT_NAME} PRIVATE ${QM_FILES}) + endif() + + # POST_BUILD steps + + # check time stamp + set(TIME_STAMP_FILE ".deploy.stamp") + add_custom_command( + TARGET ${PROJECT_NAME} + POST_BUILD + WORKING_DIRECTORY "$<TARGET_FILE_DIR:${PROJECT_NAME}>" + COMMAND ${CMAKE_COMMAND} -DTIME_STAMP_FILE=${TIME_STAMP_FILE} + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/time_stamp_check.cmake) + + # copy runtime files and run windeployqt on target and deploy Qt libs + add_custom_command( + TARGET ${PROJECT_NAME} + POST_BUILD + WORKING_DIRECTORY "$<TARGET_FILE_DIR:${PROJECT_NAME}>" + COMMAND ${CMAKE_COMMAND} -DTIME_STAMP_FILE=${TIME_STAMP_FILE} + -DCOPY_TO_PATH=$<TARGET_FILE_DIR:${PROJECT_NAME}> + -DDRING_PATH=${DRING} + -DPROJECT_ROOT_DIR=${PROJECT_SOURCE_DIR} + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/windows_daemon_deploy.cmake) + + add_custom_command( + TARGET ${PROJECT_NAME} + POST_BUILD + WORKING_DIRECTORY "$<TARGET_FILE_DIR:${PROJECT_NAME}>" + COMMAND ${CMAKE_COMMAND} -DTIME_STAMP_FILE=${TIME_STAMP_FILE} + -DWIN_DEPLOY_QT_PATH=${CMAKE_PREFIX_PATH}/bin + -DQML_SRC_DIR=${APP_SRC_DIR} + -DEXE_NAME=$<TARGET_FILE:${PROJECT_NAME}> + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/windows_qt_deploy.cmake) + + # create time stamp + add_custom_command( + TARGET ${PROJECT_NAME} + POST_BUILD + WORKING_DIRECTORY "$<TARGET_FILE_DIR:${PROJECT_NAME}>" + COMMAND ${CMAKE_COMMAND} -DTIME_STAMP_FILE=${TIME_STAMP_FILE} + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/time_stamp_create.cmake) + + # executable name + set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "Jami") elseif (NOT APPLE) - target_link_libraries(${PROJECT_NAME} PRIVATE - ${QT_LIBS} - ${LRC_LIB_NAME} - ${qrencode} - ${X11} - ${LIBNM_LIBRARIES} - ${LIBNOTIFY_LIBRARIES} - ${LIBGDKPIXBUF_LIBRARIES} - ${GLIB_LIBRARIES} - ${GIO_LIBRARIES}) - - # Installation rules - install(TARGETS jami-qt - RUNTIME DESTINATION bin) - - # install .desktop in XDG desktop dir so that it is recognized by the system - install(FILES ${PROJECT_SOURCE_DIR}/jami-qt.desktop - DESTINATION ${JAMI_DATA_PREFIX}/applications) - - # install .desktop in the jami-qt data dir, so that it can be copied to the - # autostart dir by the client - install(FILES ${PROJECT_SOURCE_DIR}/jami-qt.desktop - DESTINATION - "${JAMI_DATA_PREFIX}/${PROJECT_NAME}" - PERMISSIONS - WORLD_READ - OWNER_WRITE - OWNER_READ - GROUP_READ - ) - - # adjust JAMI_DATA_PREFIX for snap package - # (this must come after all 'install' commands that refer to - # JAMI_DATA_PREFIX; the following value is not meant to be used for - # any install destinations) - if(DEFINED ENV{SNAPCRAFT_PROJECT_NAME}) - set(JAMI_DATA_PREFIX "/snap/$ENV{SNAPCRAFT_PROJECT_NAME}/current/usr/share") - endif() - - # (this must come after the above adjustment to JAMI_DATA_PREFIX) - target_compile_definitions(jami-qt PRIVATE JAMI_INSTALL_PREFIX="${JAMI_DATA_PREFIX}") - - # logos - install(FILES resources/images/jami.svg - DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/scalable/apps) - - install(FILES resources/images/jami-48px.png - DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/48x48/apps - RENAME jami.png) - - install(FILES resources/images/jami-32px.xpm - DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps - RENAME jami.xpm) - - install(FILES jami-qt.appdata.xml - DESTINATION ${CMAKE_INSTALL_PREFIX}/share/metainfo) - - # install jami launcher that selects between clients - install( - FILES - "${PROJECT_SOURCE_DIR}/src/app/jami" - DESTINATION - ${CMAKE_INSTALL_PREFIX}/bin - PERMISSIONS - WORLD_READ - OWNER_WRITE - OWNER_READ - GROUP_READ - OWNER_EXECUTE - GROUP_EXECUTE - WORLD_EXECUTE) - - # add a target to generate API documentation with Doxygen and graphviz-dot - find_package(Doxygen) - find_program(dot "dot") - if(Doxygen_FOUND AND dot) - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/doc/Doxyfile.in ${CMAKE_CURRENT_SOURCE_DIR}/doc/Doxyfile @ONLY) - add_custom_target(doc - COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/doc/Doxyfile - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc - COMMENT "Generating API documentation with Doxygen" VERBATIM) - - # create doc/README.md symlink to README since Doxygen doesn't understand file with no extension - add_custom_command( - TARGET doc - PRE_BUILD - COMMAND ln -sf ${CMAKE_CURRENT_SOURCE_DIR}/README ${CMAKE_CURRENT_SOURCE_DIR}/doc/README.md) - endif() - - # translations - if(Qt${QT_VERSION_MAJOR}LinguistTools_FOUND) - message("Releasing and copying translation files") - file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/share/ring/translations/") - file(GLOB TS_FILES ${PROJECT_SOURCE_DIR}/translations/*.ts) - set_source_files_properties(${TS_FILES} PROPERTIES OUTPUT_LOCATION "share/ring/translations") - - qt_add_translation(QM_FILES ${TS_FILES}) - add_custom_target(translations ALL DEPENDS ${QM_FILES}) - install(DIRECTORY "${CMAKE_BINARY_DIR}/share/ring/translations/" - DESTINATION ${CMAKE_INSTALL_PREFIX}/share/ring/translations) - endif() - - # uninstall + target_link_libraries( + ${PROJECT_NAME} + PRIVATE + ${QT_LIBS} + ${LIBCLIENT_NAME} + ${qrencode} + ${X11} + ${LIBNM_LIBRARIES} + ${LIBNOTIFY_LIBRARIES} + ${LIBGDKPIXBUF_LIBRARIES} + ${GLIB_LIBRARIES} + ${GIO_LIBRARIES} + ${XCB_LIBRARIES}) + + # Installation rules + install( + TARGETS ${PROJECT_NAME} + RUNTIME DESTINATION bin) + + # Install .desktop in XDG desktop direcory so that it is recognized + # by the system. + install( + FILES ${PROJECT_SOURCE_DIR}/jami-qt.desktop + DESTINATION ${JAMI_DATA_PREFIX}/applications) + + # Install .desktop in the jami-qt data directory, so that it can be + # copied to the autostart directory by the client. + install( + FILES ${PROJECT_SOURCE_DIR}/jami-qt.desktop + DESTINATION "${JAMI_DATA_PREFIX}/${PROJECT_NAME}" + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) # 644 + + # Adjust JAMI_DATA_PREFIX for snap package. + # (This must come after all 'install' commands that refer to + # JAMI_DATA_PREFIX; the following value is not meant to be used + # for any install destinations.) + if(DEFINED ENV{SNAPCRAFT_PROJECT_NAME}) + set(JAMI_DATA_PREFIX + "/snap/$ENV{SNAPCRAFT_PROJECT_NAME}/current/usr/share") + endif() + + # (This must come after the above adjustment to JAMI_DATA_PREFIX.) + target_compile_definitions( + ${PROJECT_NAME} + PRIVATE + JAMI_INSTALL_PREFIX="${JAMI_DATA_PREFIX}") + + # Logos + install( + FILES resources/images/jami.svg + DESTINATION + ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/scalable/apps) + + install( + FILES resources/images/jami-48px.png + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/48x48/apps + RENAME jami.png) + + install( + FILES resources/images/jami-32px.xpm + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps + RENAME jami.xpm) + + install( + FILES jami-qt.appdata.xml + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/metainfo) + + # Install 'jami' launcher that automatically chooses between clients + install( + FILES + "${APP_SRC_DIR}/jami" + DESTINATION + ${CMAKE_INSTALL_PREFIX}/bin + PERMISSIONS + OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) # 755 + + # Add a target to generate API documentation using Doxygen and + # graphviz-dot. + find_package(Doxygen) + find_program(dot "dot") + if(Doxygen_FOUND AND dot) configure_file( - "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" - IMMEDIATE @ONLY) - - add_custom_target(uninstall - COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) + ${CMAKE_CURRENT_SOURCE_DIR}/doc/Doxyfile.in + ${CMAKE_CURRENT_SOURCE_DIR}/doc/Doxyfile + @ONLY) + add_custom_target( + doc + COMMAND + ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/doc/Doxyfile + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/doc + COMMENT "Generating API documentation with Doxygen" + VERBATIM) + + # Create doc/README.md symlink to README since Doxygen doesn't + # understand file with no extension. + add_custom_command( + TARGET doc + PRE_BUILD + COMMAND + ln -sf ${CMAKE_CURRENT_SOURCE_DIR}/README ${CMAKE_CURRENT_SOURCE_DIR}/doc/README.md) + endif() + + # translations + if(Qt${QT_VERSION_MAJOR}LinguistTools_FOUND) + message("Releasing and copying translation files") + file(MAKE_DIRECTORY + "${CMAKE_BINARY_DIR}/share/jami/translations/") + file(GLOB TS_FILES ${PROJECT_SOURCE_DIR}/translations/*.ts) + set_source_files_properties( + ${TS_FILES} + PROPERTIES + OUTPUT_LOCATION "share/jami/translations") + + qt_add_translation(QM_FILES ${TS_FILES}) + add_custom_target(translations ALL DEPENDS ${QM_FILES}) + install(DIRECTORY "${CMAKE_BINARY_DIR}/share/jami/translations/" + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/jami/translations) + endif() + + # uninstall rule + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE + @ONLY) + + add_custom_target( + uninstall + COMMAND + ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) else() - set(resources ${CMAKE_CURRENT_SOURCE_DIR}/resources/images/jami.icns) - set(libs ${QT_LIBS} ${LRC_LIB_NAME} ${SYSTEM_CONFIGURATUION} qrencode) - if(ENABLE_SPARKLE) - set(resources ${resources} ${PUBLIC_KEY} ${SPARKLE_FRAMEWORK}) - set(libs ${libs} ${SPARKLE_FRAMEWORK}) - endif(ENABLE_SPARKLE) - target_sources(${PROJECT_NAME} PRIVATE ${resources}) - target_link_libraries(${PROJECT_NAME} PRIVATE ${libs}) - - # translations - if(Qt${QT_VERSION_MAJOR}LinguistTools_FOUND) - set(LRC ${PROJECT_SOURCE_DIR}/../lrc) - set(APP_CONTAINER "${CMAKE_BINARY_DIR}/${PROJECT_NAME}.app/Contents") - file(GLOB TS_CLIENT_FILES ${PROJECT_SOURCE_DIR}/translations/*.ts) - file(GLOB TS_LRC_FILES ${LRC}/translations/*.ts) - - # generate lproj folders - FOREACH(QM_FILE ${TS_LRC_FILES}) - # Extract language code from filename - GET_FILENAME_COMPONENT(FILENAME ${QM_FILE} NAME_WE) - STRING(REGEX REPLACE "^lrc_" "" LANG ${FILENAME}) - file(MAKE_DIRECTORY ${APP_CONTAINER}/Resources/${LANG}.lproj) - ENDFOREACH() - set_source_files_properties(${TS_CLIENT_FILES} PROPERTIES OUTPUT_LOCATION - "${APP_CONTAINER}/Resources/share/ring/translations") - set_source_files_properties(${TS_LRC_FILES} PROPERTIES OUTPUT_LOCATION - "${APP_CONTAINER}/Resources/share/libringclient/translations") - - qt_add_translation(QM_CLIENT_FILES ${TS_CLIENT_FILES}) - qt_add_translation(QM_LRC_FILES ${TS_LRC_FILES}) - target_sources(${PROJECT_NAME} PRIVATE ${QM_CLIENT_FILES}) - target_sources(${PROJECT_NAME} PRIVATE ${QM_LRC_FILES}) - endif() - set_target_properties(${PROJECT_NAME} PROPERTIES - MACOSX_BUNDLE TRUE - MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/resources/Info.plist" - MACOSX_BUNDLE_EXECUTABLE_NAME "${PROJ_NAME}" - MACOSX_BUNDLE_ICON_FILE "jami.icns" - MACOSX_BUNDLE_GUI_IDENTIFIER "${BUNDLE_ID}" - MACOSX_BUNDLE_SHORT_VERSION_STRING "${JAMI_VERSION}" - MACOSX_BUNDLE_BUNDLE_VERSION "${JAMI_BUILD}" - MACOSX_BUNDLE_COPYRIGHT "${PROJ_COPYRIGHT}" - SPARKLE_URL "${SPARKLE_URL}" - XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "${CMAKE_CURRENT_SOURCE_DIR}/resources/entitlements/Jami.entitlements" - XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME TRUE) - if(DEPLOY) - add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -DQML_SRC_DIR=${APP_SRC_DIR} - -DMAC_DEPLOY_QT_PATH=${CMAKE_PREFIX_PATH}/bin - -DEXE_NAME="${CMAKE_BINARY_DIR}/${PROJECT_NAME}.app" - -DSPARKLE_PATH=${SPARKLE_FRAMEWORK} - -DENABLE_SPARKLE=${ENABLE_SPARKLE} - -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/macos_qt_deploy.cmake) - endif() + set(resources + ${CMAKE_CURRENT_SOURCE_DIR}/resources/images/jami.icns) + set(libs ${QT_LIBS} ${SYSTEM_CONFIGURATUION} qrencode) + if(ENABLE_SPARKLE) + set(resources ${resources} ${PUBLIC_KEY} ${SPARKLE_FRAMEWORK}) + set(libs ${libs} ${SPARKLE_FRAMEWORK}) + endif(ENABLE_SPARKLE) + target_sources(${PROJECT_NAME} PRIVATE ${resources}) + target_link_libraries(${PROJECT_NAME} PRIVATE ${libs}) + + # translations + if(Qt${QT_VERSION_MAJOR}LinguistTools_FOUND) + set(APP_CONTAINER + "${CMAKE_BINARY_DIR}/${PROJECT_NAME}.app/Contents") + file(GLOB TS_FILES ${PROJECT_SOURCE_DIR}/translations/*.ts) + + # Generate lproj folders. + foreach(QM_FILE ${TS_FILES}) + # Extract language code from filename. + get_filename_component(FILENAME ${QM_FILE} NAME_WE) + string(REGEX REPLACE "^lrc_" "" LANG ${FILENAME}) + file(MAKE_DIRECTORY ${APP_CONTAINER}/Resources/${LANG}.lproj) + endforeach() + set_source_files_properties( + ${TS_FILES} + PROPERTIES OUTPUT_LOCATION + "${APP_CONTAINER}/Resources/share/jami/translations") + + qt_add_translation(QM_FILES ${TS_FILES}) + target_sources(${PROJECT_NAME} PRIVATE ${QM_FILES}) + endif() + set_target_properties( + ${PROJECT_NAME} + PROPERTIES + MACOSX_BUNDLE TRUE + MACOSX_BUNDLE_INFO_PLIST + "${CMAKE_CURRENT_SOURCE_DIR}/resources/Info.plist" + MACOSX_BUNDLE_EXECUTABLE_NAME "${PROJ_NAME}" + MACOSX_BUNDLE_ICON_FILE "jami.icns" + MACOSX_BUNDLE_GUI_IDENTIFIER "${BUNDLE_ID}" + MACOSX_BUNDLE_SHORT_VERSION_STRING "${JAMI_VERSION}" + MACOSX_BUNDLE_BUNDLE_VERSION "${JAMI_BUILD}" + MACOSX_BUNDLE_COPYRIGHT "${PROJ_COPYRIGHT}" + SPARKLE_URL "${SPARKLE_URL}" + XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS + "${CMAKE_CURRENT_SOURCE_DIR}/resources/entitlements/Jami.entitlements" + XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME TRUE) + if(DEPLOY) + add_custom_command( + TARGET ${PROJECT_NAME} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -DQML_SRC_DIR=${APP_SRC_DIR} + -DMAC_DEPLOY_QT_PATH=${CMAKE_PREFIX_PATH}/bin + -DEXE_NAME="${CMAKE_BINARY_DIR}/${PROJECT_NAME}.app" + -DSPARKLE_PATH=${SPARKLE_FRAMEWORK} + -DENABLE_SPARKLE=${ENABLE_SPARKLE} + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/macos_qt_deploy.cmake) + endif() endif() qt_import_qml_plugins(${PROJECT_NAME}) @@ -725,6 +740,6 @@ qt_finalize_executable(${PROJECT_NAME}) # test if(ENABLE_TESTS) - message("Add Jami tests") - add_subdirectory(tests) + message("Add Jami tests") + add_subdirectory(tests) endif() diff --git a/cmake/FindLibJami.cmake b/cmake/FindLibJami.cmake new file mode 100644 index 0000000000000000000000000000000000000000..6594076a9ca4d5eebc2a33324401481deecfbed7 --- /dev/null +++ b/cmake/FindLibJami.cmake @@ -0,0 +1,131 @@ +# Copyright (C) 2015-2022 Savoir-faire Linux Inc. +# +# Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com> +# Author: Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> +# Author: Amin Bandali <amin.bandali@savoirfairelinux.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +# Once done, this find module will set: +# +# LIBJAMI_INCLUDE_DIRS - libjami include directories +# LIBJAMI_FOUND - whether it was able to find the include directories +# LIBJAMI_LIB - path to libjami or libring library + +set(LIBJAMI_FOUND true) + +if(EXISTS ${LIBJAMI_INCLUDE_DIR}/jami.h) + set(LIBJAMI_INCLUDE_DIRS ${LIBJAMI_INCLUDE_DIR}) +elseif(EXISTS ${LIBJAMI_BUILD_DIR}/jami/jami.h) + set(LIBJAMI_INCLUDE_DIRS ${LIBJAMI_BUILD_DIR}/jami) +elseif(EXISTS ${RING_INCLUDE_DIR}/jami.h) + set(LIBJAMI_INCLUDE_DIRS ${RING_INCLUDE_DIR}) +elseif(EXISTS ${RING_BUILD_DIR}/jami/jami.h) + set(LIBJAMI_INCLUDE_DIRS ${RING_BUILD_DIR}/jami) +elseif(EXISTS ${CMAKE_INSTALL_PREFIX}/include/jami/jami.h) + set(LIBJAMI_INCLUDE_DIRS ${CMAKE_INSTALL_PREFIX}/include/jami) +else() + message(STATUS "Jami daemon headers not found! +Set -DLIBJAMI_BUILD_DIR or -DCMAKE_INSTALL_PREFIX") + set(LIBJAMI_FOUND false) +endif() + +# Save the current value of CMAKE_FIND_LIBRARY_SUFFIXES. +set(CMAKE_FIND_LIBRARY_SUFFIXES_orig ${CMAKE_FIND_LIBRARY_SUFFIXES}) + +set(CMAKE_FIND_LIBRARY_SUFFIXES ".dylib;.so;.dll") + +# Search only in these given PATHS. +find_library(LIBJAMI_LIB NAMES jami + PATHS ${LIBJAMI_BUILD_DIR}/.libs + PATHS ${RING_BUILD_DIR}/.libs + PATHS ${CMAKE_INSTALL_PREFIX}/lib + PATHS ${CMAKE_INSTALL_PREFIX}/libexec + PATHS ${CMAKE_INSTALL_PREFIX}/bin + NO_DEFAULT_PATH) +if(NOT LIBJAMI_LIB) + find_library(LIBJAMI_LIB NAMES ring + PATHS ${LIBJAMI_BUILD_DIR}/.libs + PATHS ${RING_BUILD_DIR}/.libs + PATHS ${CMAKE_INSTALL_PREFIX}/lib + PATHS ${CMAKE_INSTALL_PREFIX}/libexec + PATHS ${CMAKE_INSTALL_PREFIX}/bin + NO_DEFAULT_PATH) +endif() + +# Search elsewhere as well (e.g. system-wide). +if(NOT LIBJAMI_LIB) + find_library(LIBJAMI_LIB NAMES jami + PATHS ${LIBJAMI_BUILD_DIR}/.libs + PATHS ${RING_BUILD_DIR}/.libs + PATHS ${CMAKE_INSTALL_PREFIX}/lib + PATHS ${CMAKE_INSTALL_PREFIX}/libexec + PATHS ${CMAKE_INSTALL_PREFIX}/bin) + if(NOT LIBJAMI_LIB) + find_library(LIBJAMI_LIB NAMES ring + PATHS ${LIBJAMI_BUILD_DIR}/.libs + PATHS ${RING_BUILD_DIR}/.libs + PATHS ${CMAKE_INSTALL_PREFIX}/lib + PATHS ${CMAKE_INSTALL_PREFIX}/libexec + PATHS ${CMAKE_INSTALL_PREFIX}/bin) + endif() +endif() + +# Try for a static version also. +if(NOT LIBJAMI_LIB) + set(CMAKE_FIND_LIBRARY_SUFFIXES ".a;.lib") + + # Search only in these given PATHS. + find_library(LIBJAMI_LIB NAMES jami + PATHS ${LIBJAMI_BUILD_DIR}/.libs + PATHS ${RING_BUILD_DIR}/.libs + PATHS ${CMAKE_INSTALL_PREFIX}/lib + PATHS ${CMAKE_INSTALL_PREFIX}/libexec + NO_DEFAULT_PATH) + if(NOT LIBJAMI_LIB) + find_library(LIBJAMI_LIB NAMES ring + PATHS ${LIBJAMI_BUILD_DIR}/.libs + PATHS ${RING_BUILD_DIR}/.libs + PATHS ${CMAKE_INSTALL_PREFIX}/lib + PATHS ${CMAKE_INSTALL_PREFIX}/libexec + NO_DEFAULT_PATH) + endif() + + # Search elsewhere as well (e.g. system-wide). + if(NOT LIBJAMI_LIB) + find_library(LIBJAMI_LIB NAMES jami + PATHS ${LIBJAMI_BUILD_DIR}/.libs + PATHS ${RING_BUILD_DIR}/.libs + PATHS ${CMAKE_INSTALL_PREFIX}/lib + PATHS ${CMAKE_INSTALL_PREFIX}/libexec) + if(NOT LIBJAMI_LIB) + find_library(LIBJAMI_LIB NAMES ring + PATHS ${LIBJAMI_BUILD_DIR}/.libs + PATHS ${RING_BUILD_DIR}/.libs + PATHS ${CMAKE_INSTALL_PREFIX}/lib + PATHS ${CMAKE_INSTALL_PREFIX}/libexec) + endif() + endif() + + if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Windows") + add_definitions(-fPIC) + endif() +endif() + +# Restore the original value of CMAKE_FIND_LIBRARY_SUFFIXES. +set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_orig}) + +message(STATUS "Jami daemon headers are in " ${LIBJAMI_INCLUDE_DIRS}) +message(STATUS "Jami daemon library is at " ${LIBJAMI_LIB}) diff --git a/src/app/appsettingsmanager.cpp b/src/app/appsettingsmanager.cpp index 0b6bef5a78d0a929ec3f54c05785078fb8793a4c..3100cc8abd42f8c2e4a1fc852c4c2d5db2fdda6f 100644 --- a/src/app/appsettingsmanager.cpp +++ b/src/app/appsettingsmanager.cpp @@ -99,13 +99,13 @@ AppSettingsManager::loadTranslations() QTranslator* lrcTranslator_lang = new QTranslator(qApp); QTranslator* lrcTranslator_name = new QTranslator(qApp); if (locale_name != locale_lang) { - if (lrcTranslator_lang->load(appDir + QDir::separator() + "libringclient" + QDir::separator() + if (lrcTranslator_lang->load(appDir + QDir::separator() + "jami" + QDir::separator() + "translations" + QDir::separator() + "lrc_" + locale_lang)) { qApp->installTranslator(lrcTranslator_lang); installedTr_.append(lrcTranslator_lang); } } - if (lrcTranslator_name->load(appDir + QDir::separator() + "libringclient" + QDir::separator() + if (lrcTranslator_name->load(appDir + QDir::separator() + "jami" + QDir::separator() + "translations" + QDir::separator() + "lrc_" + locale_name)) { qApp->installTranslator(lrcTranslator_name); installedTr_.append(lrcTranslator_name); @@ -114,14 +114,14 @@ AppSettingsManager::loadTranslations() QTranslator* mainTranslator_lang = new QTranslator(qApp); QTranslator* mainTranslator_name = new QTranslator(qApp); if (locale_name != locale_lang) { - if (mainTranslator_lang->load(appDir + QDir::separator() + "ring" + QDir::separator() + if (mainTranslator_lang->load(appDir + QDir::separator() + "jami" + QDir::separator() + "translations" + QDir::separator() + "ring_client_windows_" + locale_lang)) { qApp->installTranslator(mainTranslator_lang); installedTr_.append(mainTranslator_lang); } } - if (mainTranslator_name->load(appDir + QDir::separator() + "ring" + QDir::separator() + if (mainTranslator_name->load(appDir + QDir::separator() + "jami" + QDir::separator() + "translations" + QDir::separator() + "ring_client_windows_" + locale_name)) { qApp->installTranslator(mainTranslator_name); diff --git a/src/app/utilsadapter.cpp b/src/app/utilsadapter.cpp index 8a239ec880f1b37d8ba2ba711ab2f3bd2a3969da..c029bfb8b5040702826e436c86a72d2be35bbc46 100644 --- a/src/app/utilsadapter.cpp +++ b/src/app/utilsadapter.cpp @@ -457,7 +457,7 @@ UtilsAdapter::supportedLang() #else QString appDir = qApp->applicationDirPath() + QDir::separator() + "share"; #endif - auto trDir = QDir(appDir + QDir::separator() + "ring" + QDir::separator() + "translations"); + auto trDir = QDir(appDir + QDir::separator() + "jami" + QDir::separator() + "translations"); QStringList trFiles = trDir.entryList(QStringList() << "ring_client_windows_*.qm", QDir::Files); QVariantMap result; result["SYSTEM"] = tr("System"); diff --git a/src/libclient/CMakeLists.txt b/src/libclient/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..8874b4f557fa2961c9e150401f4a0fe2e9ccbbe5 --- /dev/null +++ b/src/libclient/CMakeLists.txt @@ -0,0 +1,510 @@ +# Copyright (C) 2015-2022 Savoir-faire Linux Inc. +# +# Author: Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> +# Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com> +# Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com> +# Author: Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com> +# Author: Alexandre Viau <alexandre.viau@savoirfairelinux.com> +# Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> +# Author: Nicolas Jager <nicolas.jager@savoirfairelinux.com> +# Author: Hugo Lefeuvre <hugo.lefeuvre@savoirfairelinux.com> +# Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> +# Author: Albert Babà <albert.babi@savoirfairelinux.com> +# Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> +# Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com> +# Author: Amin Bandali <amin.bandali@savoirfairelinux.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +cmake_minimum_required(VERSION 3.16) + +project(jami-libclient) + +# First, check if the compiler is new enough. Most versions of Clang +# are fine until specific problems arise. Checking for GCC is enough. +if(CMAKE_COMPILER_IS_GNUCC) + execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion + OUTPUT_VARIABLE GCC_VERSION) + if(GCC_VERSION VERSION_GREATER_EQUAL 4.8) + message(STATUS "Found GCC version >= 4.8: " ${GCC_VERSION}) + else() + message(FATAL_ERROR "Your version of GCC is too old, \ +please install GCC 4.8 or later") + endif() +endif() + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_FLAGS_DEBUG "-Og -ggdb") + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_INCLUDE_CURRENT_DIR ON) +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH true) + +# libjami (daemon) +set(CMAKE_MODULE_PATH + ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cmake") +find_package(LibJami REQUIRED) +if(LIBJAMI_FOUND) + include_directories(${LIBJAMI_INCLUDE_DIRS}) +endif() + +string(SUBSTRING ${CMAKE_GENERATOR} 0 14 CMAKE_GENERATOR_SHORT) +if(CMAKE_GENERATOR_SHORT MATCHES "Visual Studio ") + message(STATUS "Generating VS project") + set(CMAKE_CXX_COMPILER_ID "MSVC") + set(ENABLE_TEST false) + add_definitions(-DUNICODE -D_UNICODE) + remove_definitions(-D_MBCS) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zi /W0 /MP /EHsc") +endif() + +if (NOT (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")) + add_definitions( + ${QT_DEFINITIONS} + -fexceptions + -O2 + # Enable some useful warnings + -Wall + -pedantic + -Wextra + -Wmissing-declarations + -Wmissing-noreturn + -Wpointer-arith + -Wcast-align + -Wwrite-strings + -Wformat-nonliteral + -Wformat-security + -Wmissing-include-dirs + -Wundef + -Wmissing-format-attribute + -Wno-reorder + -Wunused + -Woverloaded-virtual + -Wvarargs) +endif() + +# Add more warnings for compilers that support it. +# I used pipelines like the following: +# curl https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc/Warning-Options.html | \ +# grep -E "^[\t ]+<br><dt><code>-W[a-zA-Z=-]*" -o | \ +# grep -E "\-W[a-zA-Z=-]*" -o > /tmp/48; +# curl https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/Warning-Options.html | \ +# grep -E "^[\t ]+<br><dt><code>-W[a-zA-Z=-]*" -o | \ +# grep -E "\-W[a-zA-Z=-]*" -o > /tmp/49; +# sort /tmp/48 /tmp/49 | uniq -u +if(CMAKE_COMPILER_IS_GNUCC) + if(GCC_VERSION VERSION_GREATER_EQUAL 4.9) + add_definitions( + -Wconditionally-supported + -Wno-cpp + -Wdouble-promotion + -Wdate-time + -Wfloat-conversion) + endif() + + if(GCC_VERSION VERSION_GREATER_EQUAL 5.1) + add_definitions( + -Wformat-signedness + -Wnormalized + -Wshift-count-negative + -Wshift-count-overflow + -Wsized-deallocation + -Wsizeof-array-argument) + endif() + + if(GCC_VERSION VERSION_GREATER_EQUAL 6.0) + add_definitions( + -Wnull-dereference + -Wshift-negative-value + -Wshift-overflow + -Wduplicated-cond) + endif() +endif() + +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_definitions( + -Wno-c++98-compat + -Wno-c++98-compat-pedantic + -Wno-unknown-pragmas + -Wno-documentation-unknown-command + -Wno-padded + -Wno-old-style-cast + -Wno-sign-conversion + -Wno-exit-time-destructors + -Wno-global-constructors + -Wno-shorten-64-to-32 + # -Weverything + ) +endif() + +if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(CMAKE_MACOSX_RPATH on) + set(CMAKE_SKIP_BUILD_RPATH false) + set(CMAKE_BUILD_WITH_INSTALL_RPATH false) + set(CMAKE_INSTALL_RPATH "${CMAKE_CURRENT_SOURCE_DIR}") +endif() + +if(NOT ENABLE_TEST) + set(ENABLE_TEST false) +endif() + +if(NOT (${CMAKE_SYSTEM_NAME} MATCHES "Linux") + OR ENABLE_LIBWRAP + # because mocks use the same interface present in qtwrapper/ + OR ENABLE_TEST) + set(ENABLE_LIBWRAP true) + set(ENABLE_LIBWRAP ${ENABLE_LIBWRAP} PARENT_SCOPE) +endif() + +if(NOT (${ENABLE_VIDEO} MATCHES false)) + message(STATUS "VIDEO enabled") + set(ENABLE_VIDEO 1 CACHE BOOL "Enable video") + add_definitions(-DENABLE_VIDEO=true) +endif() + +if(NOT (${ENABLE_PLUGIN} MATCHES false)) + message(STATUS "PLUGIN enabled") + set(ENABLE_PLUGIN 1 CACHE BOOL "Enable plugin") + add_definitions(-DENABLE_PLUGIN=true) +endif() + +set(CHK_FREEABLE_BEFORE_ERASE_ACCOUNT_DESCRIPTION + "Check that an account has been marked freeable by the client +before freeing the structures. This avoids various race conditions +conditions while removing accounts but may not be supported by all +clients. ON by default on GNU/Linux systems, otherwise OFF.") + +if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") + option(CHK_FREEABLE_BEFORE_ERASE_ACCOUNT + CHK_FREEABLE_BEFORE_ERASE_ACCOUNT_DESCRIPTION ON) +else() + option(CHK_FREEABLE_BEFORE_ERASE_ACCOUNT + CHK_FREEABLE_BEFORE_ERASE_ACCOUNT_DESCRIPTION OFF) +endif() + +if(CHK_FREEABLE_BEFORE_ERASE_ACCOUNT) + add_definitions(-DCHK_FREEABLE_BEFORE_ERASE_ACCOUNT) +endif() + +include_directories(SYSTEM ${QT_INCLUDES}) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +# Here we let find_package(<PackageName>...) try to find Qt 6. +# If it is found, find_package will succeed, and the CMake variable +# QT_VERSION_MAJOR will be set to 6. +if(QT6_VER AND QT6_PATH) + find_package(QT NAMES Qt6 REQUIRED + PATHS ${QT6_PATH} NO_DEFAULT_PATH) +else() + find_package(QT NAMES Qt6 REQUIRED) +endif() +if (${QT_VERSION_MAJOR} STRLESS 6) + if (${QT_VERSION_MINOR} STRLESS 2) + message(FATAL_ERROR "Qt 6.2 or higher is required.") + endif() +endif() + +set(QT_MODULES Core Gui Sql) +if(NOT ENABLE_LIBWRAP) + list(APPEND QT_MODULES DBus) +endif() + +if(QT6_VER AND QT6_PATH) + message(STATUS "Using custom Qt version") + find_package(Qt${QT_VERSION_MAJOR} + REQUIRED COMPONENTS ${QT_MODULES} + OPTIONAL_COMPONENTS LinguistTools + PATHS ${QT6_PATH} NO_DEFAULT_PATH) +else() + find_package(Qt${QT_VERSION_MAJOR} + REQUIRED COMPONENTS ${QT_MODULES} + OPTIONAL_COMPONENTS LinguistTools) +endif() + +if(ENABLE_LIBWRAP) + # The daemon is only required for when using direct linking + if(NOT LIBJAMI_LIB) + message(FATAL_ERROR "Jami daemon library is required when \ +building with ENABLE_LIBWRAP") + endif() + + # Use native calls (no DBus) + add_definitions(-DENABLE_LIBWRAP=true) + if (NOT (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")) + add_definitions(-Wno-unknown-pragmas) + endif() + message(STATUS "Compiling with qtwrapper enabled, \ +Qt${QT_VERSION_MAJOR} enabled.") + + add_subdirectory(qtwrapper) + include_directories(qtwrapper) + + if(${VERBOSE_IPC} MATCHES true) + message(STATUS "Adding more debug output") + add_definitions(-DVERBOSE_IPC=true) + endif() +endif() + +set(LIBCLIENT_SOURCES + # data objects + uri.cpp + + # models + contactmodel.cpp + callparticipantsmodel.cpp + newcallmodel.cpp + newdevicemodel.cpp + newcodecmodel.cpp + conversationmodel.cpp + database.cpp + authority/daemon.cpp + authority/storagehelper.cpp + lrc.cpp + newaccountmodel.cpp + peerdiscoverymodel.cpp + callbackshandler.cpp + behaviorcontroller.cpp + datatransfermodel.cpp + messagelistmodel.cpp + + # communication + dbus/configurationmanager.cpp + dbus/callmanager.cpp + dbus/instancemanager.cpp + dbus/videomanager.cpp + dbus/presencemanager.cpp + dbus/pluginmanager.cpp + + # default interface implementations + globalinstances.cpp + pixmapmanipulatordefault.cpp + dbuserrorhandlerdefault.cpp + + # other + avmodel.cpp + pluginmodel.cpp + namedirectory.cpp + smartinfohub.cpp + chatview.cpp + renderer.cpp) + +set(LIBCLIENT_HEADERS + uri.h + globalinstances.h + pixmapmanipulatordefault.h + dbuserrorhandlerdefault.h + smartinfohub.h + vcard.h + namedirectory.h + messagelistmodel.h + + # interfaces + interfaces/pixmapmanipulatori.h + interfaces/dbuserrorhandleri.h + + # extra + typedefs.h + containerview.h + renderer.h) + +set(LIBCLIENT_HEADERS_API + api/account.h + api/avmodel.h + api/behaviorcontroller.h + api/chatview.h + api/call.h + api/contact.h + api/conversation.h + api/contactmodel.h + api/conversationmodel.h + api/datatransfermodel.h + api/datatransfer.h + api/interaction.h + api/lrc.h + api/member.h + api/newaccountmodel.h + api/newcallmodel.h + api/callparticipantsmodel.h + api/newcodecmodel.h + api/newdevicemodel.h + api/pluginmodel.h + api/peerdiscoverymodel.h + api/profile.h + api/video.h) + +# For libavutil/avframe. +set(LIBJAMI_CONTRIB_DIR + "${PROJECT_SOURCE_DIR}/../../../daemon/contrib") +find_path(AVUTIL_INCLUDE_DIR libavutil/avutil.h + PATHS + ${LIBJAMI_CONTRIB_DIR}/native/ffmpeg + ${LIBJAMI_CONTRIB_DIR}/build/ffmpeg/Build/win32/x64/include) +include_directories(${AVUTIL_INCLUDE_DIR}) + +if(ENABLE_LIBWRAP) + list(APPEND LIBCLIENT_HEADERS directrenderer.h) + list(APPEND LIBCLIENT_SOURCES directrenderer.cpp) +else() + list(APPEND LIBCLIENT_HEADERS shmrenderer.h) + list(APPEND LIBCLIENT_SOURCES shmrenderer.cpp) + + # Build DBus API + if(DEFINED RING_XML_INTERFACES_DIR) + set(dbus_xml_introspecs_path ${RING_XML_INTERFACES_DIR}) + elseif(DEFINED LIBJAMI_XML_INTERFACES_DIR) + set(dbus_xml_introspecs_path ${LIBJAMI_XML_INTERFACES_DIR}) + elseif(EXISTS "${LIBJAMI_BUILD_DIR}/../bin/dbus") + set(dbus_xml_introspecs_path ${LIBJAMI_BUILD_DIR}/../bin/dbus) + else() + set(dbus_xml_introspecs_path + ${CMAKE_INSTALL_PREFIX}/share/dbus-1/interfaces) + endif() + message(STATUS "Using Jami (Ring) DBus-XML interfaces in \ +${dbus_xml_introspecs_path}") + + set(presencemanager_xml + ${dbus_xml_introspecs_path}/cx.ring.Ring.PresenceManager.xml) + set(dbus_metatype_path "dbus/metatypes.h") + set_source_files_properties( + ${presencemanager_xml} + PROPERTIES + CLASSNAME PresenceManagerInterface + INCLUDE ${dbus_metatype_path}) + + set(configurationmanager_xml + ${dbus_xml_introspecs_path}/cx.ring.Ring.ConfigurationManager.xml) + set_source_files_properties( + ${configurationmanager_xml} + PROPERTIES + CLASSNAME ConfigurationManagerInterface + INCLUDE ${dbus_metatype_path}) + + set(callmanager_xml + ${dbus_xml_introspecs_path}/cx.ring.Ring.CallManager.xml) + set_source_files_properties( + ${callmanager_xml} + PROPERTIES + CLASSNAME CallManagerInterface + INCLUDE ${dbus_metatype_path}) + + set(video_xml + ${dbus_xml_introspecs_path}/cx.ring.Ring.VideoManager.xml) + set_source_files_properties( + ${video_xml} + PROPERTIES + CLASSNAME VideoManagerInterface + INCLUDE ${dbus_metatype_path}) + + set(plugin_xml + ${dbus_xml_introspecs_path}/cx.ring.Ring.PluginManagerInterface.xml) + set_source_files_properties( + ${plugin_xml} + PROPERTIES + CLASSNAME PluginManagerInterface + INCLUDE ${dbus_metatype_path}) + + set(instance_xml + ${dbus_xml_introspecs_path}/cx.ring.Ring.Instance.xml) + set_source_files_properties( + ${instance_xml} + PROPERTIES + CLASSNAME InstanceManagerInterface + INCLUDE ${dbus_metatype_path}) + + qt_add_dbus_interface( + LIBCLIENT_SOURCES + ${presencemanager_xml} + presencemanager_dbus_interface) + + qt_add_dbus_interface( + LIBCLIENT_SOURCES + ${configurationmanager_xml} + configurationmanager_dbus_interface) + + qt_add_dbus_interface( + LIBCLIENT_SOURCES + ${callmanager_xml} + callmanager_dbus_interface) + + qt_add_dbus_interface( + LIBCLIENT_SOURCES + ${video_xml} + video_dbus_interface) + + qt_add_dbus_interface( + LIBCLIENT_SOURCES + ${plugin_xml} + plugin_dbus_interface) + + qt_add_dbus_interface( + LIBCLIENT_SOURCES + ${instance_xml} + instance_dbus_interface) +endif() + +# Manually wrap libjamiclient's private headers and interfaces. +set(LIBCLIENT_HEADERS_PRIVATE + private/namedirectory_p.h + private/smartInfoHub_p.h) + +if(ENABLE_LIBWRAP AND (NOT ENABLE_TEST)) + list(APPEND LIBCLIENT_HEADERS_PRIVATE + qtwrapper/callmanager_wrap.h + qtwrapper/configurationmanager_wrap.h + qtwrapper/instancemanager_wrap.h + qtwrapper/presencemanager_wrap.h + qtwrapper/videomanager_wrap.h + qtwrapper/pluginmanager_wrap.h) +endif() + +if(NOT ENABLE_TEST) + qt_wrap_cpp(LIBCLIENT_HEADERS_MOC ${LIBCLIENT_HEADERS_PRIVATE}) +endif() + +foreach(MODULE ${QT_MODULES}) + list(APPEND QT_LIBS "Qt::${MODULE}") +endforeach() + +set(LIBCLIENT_NAME "libjamiclient") +set(LIBCLIENT_VERSION "1.0.0") +add_library(${LIBCLIENT_NAME} STATIC + ${LIBCLIENT_SOURCES} + ${LIBCLIENT_HEADERS_API} + ${LIBCLIENT_HEADERS_MOC}) +foreach(QT_LIB ${QT_LIBS}) + target_link_libraries(${LIBCLIENT_NAME} ${QT_LIB}) +endforeach() +if(ENABLE_LIBWRAP) + target_link_libraries(${LIBCLIENT_NAME} qtwrapper ${LIBJAMI_LIB}) +endif() +if (NOT (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")) + target_link_libraries(${LIBCLIENT_NAME} -lpthread) + if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") + target_link_libraries(${LIBCLIENT_NAME} -lrt) + endif() +endif() +set_target_properties(${LIBCLIENT_NAME} + PROPERTIES VERSION ${LIBCLIENT_VERSION}) +target_include_directories(${LIBCLIENT_NAME} + PRIVATE ${AVUTIL_INCLUDE_DIR}) + +# Set these in the parent scope for use from the top-level +# CMakeLists.txt file. +set(LIBCLIENT_NAME ${LIBCLIENT_NAME} PARENT_SCOPE) +set(LIBCLIENT_VERSION ${LIBCLIENT_VERSION} PARENT_SCOPE) diff --git a/src/libclient/api/account.h b/src/libclient/api/account.h new file mode 100644 index 0000000000000000000000000000000000000000..f9c38d0aa4be67ec26325e38867257200dbf5077 --- /dev/null +++ b/src/libclient/api/account.h @@ -0,0 +1,245 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#include "profile.h" + +#include "typedefs.h" + +#include <memory> + +#include <QString> + +namespace lrc { + +namespace api { + +class ContactModel; +class ConversationModel; +class NewCallModel; +class NewAccountModel; +class NewDeviceModel; +class NewCodecModel; +class PeerDiscoveryModel; +class DataTransferModel; + +namespace account { +Q_NAMESPACE +Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") + +enum class Type { INVALID, JAMI, SIP }; +Q_ENUM_NS(Type) + +#pragma push_macro("REGISTERED") +#undef REGISTERED + +enum class Status { INVALID, ERROR_NEED_MIGRATION, INITIALIZING, UNREGISTERED, TRYING, REGISTERED }; +Q_ENUM_NS(Status) + +static inline account::Status +to_status(const QString& type) +{ + if (type == "INITIALIZING") + return account::Status::INITIALIZING; + else if (type == "UNREGISTERED") + return account::Status::UNREGISTERED; + else if (type == "TRYING") + return account::Status::TRYING; + else if (type == "REGISTERED" || type == "READY") + return account::Status::REGISTERED; + else if (type == "ERROR_NEED_MIGRATION") + return account::Status::ERROR_NEED_MIGRATION; + else + return account::Status::INVALID; +} + +#pragma pop_macro("REGISTERED") + +enum class KeyExchangeProtocol { NONE, SDES }; +Q_ENUM_NS(KeyExchangeProtocol) + +enum class TlsMethod { DEFAULT, TLSv1, TLSv1_1, TLSv1_2 }; +Q_ENUM_NS(TlsMethod) + +struct ConfProperties_t +{ + QString mailbox; + QString dtmfType; + bool autoAnswer; + bool sendReadReceipt; + bool isRendezVous; + int activeCallLimit; + QString hostname; + QString username; + QString routeset; + QString password; + QString realm; + QString localInterface; + QString deviceId; + QString deviceName; + QString managerUri; + QString managerUsername; + bool publishedSameAsLocal; + int localPort; + int publishedPort; + QString publishedAddress; + QString userAgent; + bool upnpEnabled; + bool hasCustomUserAgent; + bool allowIncoming; + bool allowIPAutoRewrite; + QString archivePassword; + bool archiveHasPassword; + QString archivePath; + QString archivePin; + bool proxyEnabled; + QString proxyServer; + QString proxyPushToken; + bool peerDiscovery; + bool accountDiscovery; + bool accountPublish; + int registrationExpire; + bool keepAliveEnabled; + QString bootstrapListUrl; + QString dhtProxyListUrl; + QString defaultModerators; + bool localModeratorsEnabled; + VectorMapStringString credentials; + struct Audio_t + { + int audioPortMax; + int audioPortMin; + } Audio; + struct Video_t + { + bool videoEnabled; + int videoPortMax; + int videoPortMin; + } Video; + struct STUN_t + { + QString server; + bool enable; + } STUN; + struct TURN_t + { + QString server; + bool enable; + QString username; + QString password; + QString realm; + } TURN; + struct Presence_t + { + bool presencePublishSupported; + bool presenceSubscribeSupported; + bool presenceEnabled; + } Presence; + struct Ringtone_t + { + QString ringtonePath; + bool ringtoneEnabled; + } Ringtone; + struct SRTP_t + { + KeyExchangeProtocol keyExchange; + bool enable; + bool rtpFallback; + } SRTP; + struct TLS_t + { + int listenerPort; + bool enable; + int port; + QString certificateListFile; + QString certificateFile; + QString privateKeyFile; + QString password; + TlsMethod method; + QString ciphers; + QString serverName; + bool verifyServer; + bool verifyClient; + bool requireClientCertificate; + int negotiationTimeoutSec; + } TLS; + struct DHT_t + { + int port; + bool PublicInCalls; + bool AllowFromTrusted; + } DHT; + struct RingNS_t + { + QString uri; + QString account; + } RingNS; + struct Registration_t + { + int expire; + } Registration; + + MapStringString toDetails() const; +}; + +// Possible account export status +enum class ExportOnRingStatus { SUCCESS = 0, WRONG_PASSWORD = 1, NETWORK_ERROR = 2, INVALID }; +Q_ENUM_NS(ExportOnRingStatus) + +enum class RegisterNameStatus { + SUCCESS = 0, + WRONG_PASSWORD = 1, + INVALID_NAME = 2, + ALREADY_TAKEN = 3, + NETWORK_ERROR = 4, + INVALID +}; +Q_ENUM_NS(RegisterNameStatus) + +enum class LookupStatus { SUCCESS = 0, INVALID_NAME = 1, NOT_FOUND = 2, ERROR = 3, INVALID }; +Q_ENUM_NS(LookupStatus) + +struct Info +{ + bool freeable = false; + bool valid = true; + QString registeredName; + Status status = account::Status::INVALID; + std::unique_ptr<lrc::api::NewCallModel> callModel; + std::unique_ptr<lrc::api::ContactModel> contactModel; + std::unique_ptr<lrc::api::ConversationModel> conversationModel; + std::unique_ptr<lrc::api::NewDeviceModel> deviceModel; + std::unique_ptr<lrc::api::NewCodecModel> codecModel; + std::unique_ptr<lrc::api::PeerDiscoveryModel> peerDiscoveryModel; + std::unique_ptr<DataTransferModel> dataTransferModel; + NewAccountModel* accountModel {nullptr}; + + // daemon config + QString id; + profile::Info profileInfo; // contains: type, alias + bool enabled; + ConfProperties_t confProperties; + + // load/save + void fromDetails(const MapStringString& details); +}; + +} // namespace account +} // namespace api +} // namespace lrc diff --git a/src/libclient/api/avmodel.h b/src/libclient/api/avmodel.h new file mode 100644 index 0000000000000000000000000000000000000000..f76d1682c0575577433a64301de1a4ed4ab38313 --- /dev/null +++ b/src/libclient/api/avmodel.h @@ -0,0 +1,326 @@ +/* + * Copyright (C) 2018-2022 Savoir-faire Linux Inc. + * Author: Hugo Lefeuvre <hugo.lefeuvre@savoirfairelinux.com> + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "api/video.h" +#include "typedefs.h" + +#include <QObject> + +#include <memory> +#include <string> +#include <vector> + +namespace lrc { + +class CallbacksHandler; +class AVModelPimpl; + +namespace api { + +class LIB_EXPORT AVModel : public QObject +{ + Q_OBJECT +public: + AVModel(const CallbacksHandler& callbacksHandler); + ~AVModel(); + + /** + * Get if hardware decoding is enabled + * @return hardware decoding enabled + */ + bool getDecodingAccelerated() const; + /** + * Enable/disable hardware decoding + * @param if hardware decoding enabled + */ + void setDecodingAccelerated(bool accelerate); + /** + * Get if hardware encoding is enabled + * @return hardware encoding enabled + */ + bool getEncodingAccelerated() const; + /** + * Enable/disable hardware encoding + * @param if hardware encoding enabled + */ + void setEncodingAccelerated(bool accelerate); + /** + * Get if hardware acceleration is enabled + * @return hardware acceleration enabled + */ + Q_INVOKABLE bool getHardwareAcceleration() const; + /** + * Enable/disable hardware acceleration + * @param if hardware acceleration enabled + */ + Q_INVOKABLE void setHardwareAcceleration(bool accelerate); + /** + * Get video devices + * @return list of devices + */ + QVector<QString> getDevices() const; + /** + * Retrieve current default video device + * @return current default video device id + */ + Q_INVOKABLE QString getDefaultDevice() const; + /** + * Set new default video device + * @param id of the device + */ + Q_INVOKABLE void setDefaultDevice(const QString& deviceId); + /** + * Retrieve current framerate/resolution/etc of a device + * @param id of the device + * @return settings of the device + */ + video::Settings getDeviceSettings(const QString& deviceId) const; + /** + * Set device settings + * @param video::Settings + */ + void setDeviceSettings(video::Settings& settings); + /** + * Retrieve all framerate/resolution/etc possibilities of a device + * @param id of the device + * @return possibilities of the device + */ + video::Capabilities getDeviceCapabilities(const QString& deviceId) const; + /** + * Get the deviceId corresponding to a given device friendly name + * @return deviceId + */ + QString getDeviceIdFromName(const QString& deviceName) const; + /** + * Get supported audio managers + * @return supported audio managers + */ + VectorString getSupportedAudioManagers() const; + /** + * Get current audio manager + * @return current audio manager + */ + QString getAudioManager() const; + /** + * Get current audio outputs + * @return audio outputs + */ + QVector<QString> getAudioOutputDevices() const; + /** + * Get current audio inputs + * @return audio inputs + */ + QVector<QString> getAudioInputDevices() const; + /** + * Get current ringtone device + * @return current ringtone device + */ + QString getRingtoneDevice() const; + /** + * Get current output device + * @return current output device + */ + QString getOutputDevice() const; + /** + * Get current input device + * @return current input device + */ + QString getInputDevice() const; + /** + * Get current state of the audio meter + * @return current state of the audio meter + */ + bool isAudioMeterActive(const QString& id = "") const; + /** + * Turn on/off the audio metering feature + * @param the new state of the meter + */ + void setAudioMeterState(bool active, const QString& id = "") const; + /** + * Starts audio device. Should only be invoked when outside of a call. + */ + void startAudioDevice() const; + /** + * Stops audio device. Should only be invoked when outside of a call. + */ + void stopAudioDevice() const; + /** + * Set current audio manager + * @param name of the new audio manager + * @return if the operation is successful + */ + Q_INVOKABLE bool setAudioManager(const QString& name); + /** + * Set current ringtone device + * @param name of the new ringtone device + */ + Q_INVOKABLE void setRingtoneDevice(const QString& name); + /** + * Set current output device + * @param name of the new output device + */ + Q_INVOKABLE void setOutputDevice(const QString& name); + /** + * Set current input device + * @param name of the new input device + */ + Q_INVOKABLE void setInputDevice(const QString& name); + /** + * Stop local record at given path + * @param path + */ + Q_INVOKABLE void stopLocalRecorder(const QString& path) const; + /** + * Start a local recorder and return it path. + * @param audioOnly + */ + Q_INVOKABLE QString startLocalMediaRecorder(const QString& videoInputId) const; + /** + * Get the current recording path + * @return recording path + */ + Q_INVOKABLE QString getRecordPath() const; + /** + * Sets the recording path + * @param path recording path + */ + Q_INVOKABLE void setRecordPath(const QString& path) const; + /** + * Whether or not to record every call + * @return always recording + */ + Q_INVOKABLE bool getAlwaysRecord() const; + /** + * Sets whether or not to record every call + * @param rec always recording + */ + Q_INVOKABLE void setAlwaysRecord(const bool& rec) const; + /** + * Whether or not local video is recorded + * @return recording preview + */ + Q_INVOKABLE bool getRecordPreview() const; + /** + * Sets whether or not to record local video + * @param rec recording preview + */ + Q_INVOKABLE void setRecordPreview(const bool& rec) const; + /** + * Gets the quality used while recording + * @return recording quality + */ + Q_INVOKABLE int getRecordQuality() const; + /** + * Sets the recording quality + * @param quality recording quality + */ + Q_INVOKABLE void setRecordQuality(const int& quality) const; + /** + * Start preview renderer. This will start the camera + * @param resource + * @return sinkId + */ + Q_INVOKABLE QString startPreview(const QString& resource); + /** + * Stop preview renderer and the camera. + * @param resource + */ + Q_INVOKABLE void stopPreview(const QString& resource); + /** + * Get the list of available windows ids + * X11: a id is of the form 0x0000000 + * @return map with windows names and ids + */ + const QVariantMap getListWindows() const; + /** + * set current using device + * @param device name + */ + Q_INVOKABLE void setCurrentVideoCaptureDevice(const QString& currentVideoCaptureDevice); + /** + * set current using device + * @return current using device name + */ + Q_INVOKABLE QString getCurrentVideoCaptureDevice() const; + /** + * clear current using device + */ + void clearCurrentVideoCaptureDevice(); + /** + * Add Renderer to renderers_ and start it + * @param id + * @param settings + * @param shmPath + */ + void addRenderer(const QString& id, const QSize& res, const QString& shmPath = {}); + + bool hasRenderer(const QString& id); + QSize getRendererSize(const QString& id); + video::Frame getRendererFrame(const QString& id); + bool useDirectRenderer() const; + +Q_SIGNALS: + /** + * Emitted when a renderer is started + * @param id of the renderer + */ + void rendererStarted(const QString& id); + /** + * Emitted when a renderer is stopped + * @param id of the renderer + */ + void rendererStopped(const QString& id); + /** + * Emitted when a new frame is requested + * @param id + */ + void frameBufferRequested(const QString& id, AVFrame* frame); + /** + * Emitted when a new frame is ready + * @param id + */ + void frameUpdated(const QString& id); + /** + * Emitted when a video device is plugged or unplugged + */ + void deviceEvent(); + /** + * Emitted when an audio device is plugged or unplugged + */ + void audioDeviceEvent(); + /** + * Audio volume level + * @param id Ringbuffer id + * @param level Volume in range [0, 1] + */ + void audioMeter(const QString& id, float level); + /** + * local recorder stopped + * @param filePath + */ + void recordPlaybackStopped(const QString& filePath); + +private: + std::unique_ptr<AVModelPimpl> pimpl_; +}; +} // namespace api +} // namespace lrc +Q_DECLARE_METATYPE(lrc::api::AVModel*) diff --git a/src/libclient/api/behaviorcontroller.h b/src/libclient/api/behaviorcontroller.h new file mode 100644 index 0000000000000000000000000000000000000000..bec07b17e37cd397c0442fa395b5065bbeb14503 --- /dev/null +++ b/src/libclient/api/behaviorcontroller.h @@ -0,0 +1,109 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#include "typedefs.h" + +#include <QObject> + +#include <memory> + +namespace lrc { + +class BehaviorControllerPimpl; + +namespace api { +class Lrc; + +namespace conversation { +struct Info; +} + +namespace interaction { +struct Info; +} + +/** + * @brief Class that helps to control behaviors from the client side. + * @note This class must only refer to the common behaviors. + */ +class LIB_EXPORT BehaviorController : public QObject +{ + Q_OBJECT + +public: + BehaviorController(); + ~BehaviorController(); + +Q_SIGNALS: + /** + * Emitted when the client should open the chat view. + */ + void showChatView(const QString& accountId, const QString& convUid) const; + /** + * Emitted when the client should ask the user whether it wants to leave a message after a + * failed call. + */ + void showLeaveMessageView(const QString& accountId, const QString& convUid) const; + /** + * Emitted when the client should open the call view. + */ + void showCallView(const QString& accountId, const QString& convUid) const; + /** + * Emitted when the client should open the incoming call view. + */ + void showIncomingCallView(const QString& accountId, const QString& convUid) const; + /** + * Emitted when the client receives a new trust request + */ + void newTrustRequest(const QString& accountId, const QString& conversationId, const QString& contactUri) const; + /** + * Emitted when a trust request has been accepted, refused or blocked + */ + void trustRequestTreated(const QString& accountId, const QString& contactUri) const; + /** + * Emitted when the client receives an unread message to display (text or file for now) + */ + void newUnreadInteraction(const QString& accountId, + const QString& conversation, + const QString& interactionId, + const interaction::Info& interaction) const; + /** + * Emitted when the unread interaction is now read + */ + void newReadInteraction(const QString& accountId, + const QString& conversation, + const QString& interactionId) const; + /** + * Emitted debugMessageReceived + */ + void debugMessageReceived(const QString& message); + /** + * Emitted audioMeter + */ + void audioMeter(const QString& id, float level); + + /** + * Emitted callStatusChanged + */ + void callStatusChanged(const QString& accountId, const QString& callId) const; +}; +} // namespace api +} // namespace lrc +Q_DECLARE_METATYPE(lrc::api::BehaviorController*) diff --git a/src/libclient/api/call.h b/src/libclient/api/call.h new file mode 100644 index 0000000000000000000000000000000000000000..628c07c2630fb6c31e31b16aa394750b23063624 --- /dev/null +++ b/src/libclient/api/call.h @@ -0,0 +1,193 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +// Qt +#include <QObject> + +// std +#include <string> +#include <ctime> +#include <chrono> + +#include "typedefs.h" + +namespace lrc { + +namespace api { + +namespace call { +Q_NAMESPACE +Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") + +enum class Status { + INVALID, + INCOMING_RINGING, + OUTGOING_RINGING, + CONNECTING, + SEARCHING, + IN_PROGRESS, + PAUSED, + INACTIVE, + ENDED, + PEER_BUSY, + TIMEOUT, + TERMINATING, + CONNECTED +}; +Q_ENUM_NS(Status) + +static inline QString +to_string(const call::Status& status) +{ + switch (status) { + case call::Status::PAUSED: + return QObject::tr("Hold"); + case call::Status::IN_PROGRESS: + return QObject::tr("Talking"); + case call::Status::INVALID: + return QObject::tr("ERROR"); + case call::Status::INCOMING_RINGING: + return QObject::tr("Incoming"); + case call::Status::OUTGOING_RINGING: + return QObject::tr("Calling"); + case call::Status::CONNECTING: + return QObject::tr("Connecting"); + case call::Status::SEARCHING: + return QObject::tr("Searching"); + case call::Status::INACTIVE: + return QObject::tr("Inactive"); + case call::Status::ENDED: + return QObject::tr("Finished"); + case call::Status::TIMEOUT: + return QObject::tr("Timeout"); + case call::Status::PEER_BUSY: + return QObject::tr("Peer busy"); + case call::Status::TERMINATING: + return QObject::tr("Finished"); + case call::Status::CONNECTED: + return QObject::tr("Communication established"); + default: + return ""; // to remove a build warning, should not happen + } +} + +/** + * Convert status from daemon into a Status + * @warning status is a string from the daemon, not from to_string() + * @param status + * @return + */ +static inline Status +to_status(const QString& status) +{ + if (status == "INCOMING") + return Status::INCOMING_RINGING; + else if (status == "CONNECTING") + return Status::CONNECTING; + else if (status == "RINGING") + return Status::OUTGOING_RINGING; + else if (status == "HUNGUP" || status == "FAILURE") + return Status::TERMINATING; + else if (status == "HOLD" || status == "ACTIVE_DETACHED") + return Status::PAUSED; + else if (status == "UNHOLD" || status == "CURRENT" || status == "ACTIVE_ATTACHED") + return Status::IN_PROGRESS; + else if (status == "PEER_BUSY") + return Status::PEER_BUSY; + else if (status == "BUSY") + return Status::TIMEOUT; + else if (status == "INACTIVE") + return Status::INACTIVE; + else if (status == "OVER") + return Status::ENDED; + return Status::INVALID; +} + +enum class Type { INVALID, DIALOG, CONFERENCE }; +Q_ENUM_NS(Type) + +enum class Layout { GRID, ONE_WITH_SMALL, ONE }; + +struct Info +{ + QString id; + std::chrono::steady_clock::time_point startTime; + Status status = Status::INVALID; + Type type = Type::INVALID; + QString peerUri; + bool isOutgoing; + bool audioMuted = false; // this flag is used to check device audio status + bool videoMuted = false; // this flag is used to check device video status + bool isAudioOnly = false; + Layout layout = Layout::GRID; + VectorMapStringString mediaList = {}; + QSet<QString> peerRec {}; + bool isConference = false; +}; + +static inline bool +canSendSIPMessage(const Info& call) +{ + switch (call.status) { + case call::Status::PAUSED: + case call::Status::IN_PROGRESS: + case call::Status::INCOMING_RINGING: + case call::Status::OUTGOING_RINGING: + case call::Status::CONNECTED: + return true; + case call::Status::INVALID: + case call::Status::CONNECTING: + case call::Status::SEARCHING: + case call::Status::INACTIVE: + case call::Status::ENDED: + case call::Status::PEER_BUSY: + case call::Status::TIMEOUT: + case call::Status::TERMINATING: + default: + return false; + } +} + +static inline bool +isTerminating(const Status& status) +{ + switch (status) { + case call::Status::INVALID: + case call::Status::INACTIVE: + case call::Status::ENDED: + case call::Status::PEER_BUSY: + case call::Status::TIMEOUT: + case call::Status::TERMINATING: + return true; + case call::Status::PAUSED: + case call::Status::IN_PROGRESS: + case call::Status::INCOMING_RINGING: + case call::Status::OUTGOING_RINGING: + case call::Status::CONNECTED: + case call::Status::CONNECTING: + case call::Status::SEARCHING: + default: + return false; + } +} + +} // namespace call +} // namespace api +} // namespace lrc diff --git a/src/libclient/api/callparticipantsmodel.h b/src/libclient/api/callparticipantsmodel.h new file mode 100644 index 0000000000000000000000000000000000000000..a699beb8ce15a8a2c3f7e8153894fb6c0979d1d8 --- /dev/null +++ b/src/libclient/api/callparticipantsmodel.h @@ -0,0 +1,193 @@ +/*! + * Copyright (C) 2022 Savoir-faire Linux Inc. + * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +// std +#include <string> +#include <ctime> +#include <chrono> +#include <mutex> + +// Qt +#include <QObject> +#include <QJsonObject> + +#include "typedefs.h" +#include "call.h" + +namespace lrc { + +namespace api { +class NewCallModel; + +namespace ParticipantsInfosStrings { +const QString URI = "uri"; +const QString DEVICE = "device"; +const QString ACTIVE = "active"; +const QString AVATAR = "avatar"; +const QString X = "x"; +const QString Y = "y"; +const QString W = "w"; +const QString H = "h"; +const QString WIDTH = "widht"; +const QString HEIGHT = "height"; +const QString VIDEOMUTED = "videoMuted"; +const QString AUDIOLOCALMUTED = "audioLocalMuted"; +const QString AUDIOMODERATORMUTED = "audioModeratorMuted"; +const QString ISMODERATOR = "isModerator"; +const QString HANDRAISED = "handRaised"; +const QString SINKID = "sinkId"; +const QString BESTNAME = "bestName"; +const QString ISLOCAL = "isLocal"; +const QString ISCONTACT = "isContact"; +const QString CALLID = "callId"; +} // namespace ParticipantsInfosStrings + +struct ParticipantInfos +{ + ParticipantInfos() {} + + ParticipantInfos(const MapStringString& infos, const QString& callId, const QString& peerId) + { + uri = infos[ParticipantsInfosStrings::URI]; + if (uri.lastIndexOf("@") > 0) + uri.truncate(uri.lastIndexOf("@")); + if (uri.isEmpty()) + uri = peerId; + device = infos[ParticipantsInfosStrings::DEVICE]; + active = infos[ParticipantsInfosStrings::ACTIVE] == "true"; + x = infos[ParticipantsInfosStrings::X].toInt(); + y = infos[ParticipantsInfosStrings::Y].toInt(); + width = infos[ParticipantsInfosStrings::W].toInt(); + height = infos[ParticipantsInfosStrings::H].toInt(); + videoMuted = infos[ParticipantsInfosStrings::VIDEOMUTED] == "true"; + audioLocalMuted = infos[ParticipantsInfosStrings::AUDIOLOCALMUTED] == "true"; + audioModeratorMuted = infos[ParticipantsInfosStrings::AUDIOMODERATORMUTED] == "true"; + isModerator = infos[ParticipantsInfosStrings::ISMODERATOR] == "true"; + handRaised = infos[ParticipantsInfosStrings::HANDRAISED] == "true"; + + if (infos[ParticipantsInfosStrings::SINKID].isEmpty()) + sinkId = callId + uri + device; + else + sinkId = infos[ParticipantsInfosStrings::SINKID]; + + bestName = ""; + } + + QString uri; + QString device; + QString sinkId; + QString bestName; + QString avatar; + bool active {false}; + int x = 0; + int y = 0; + int width = 0; + int height = 0; + bool audioLocalMuted {false}; + bool audioModeratorMuted {false}; + bool videoMuted {false}; + bool isModerator {false}; + bool islocal {false}; + bool isContact {false}; + bool handRaised {false}; + + bool operator==(const ParticipantInfos& other) const + { + return uri == other.uri && sinkId == other.sinkId && active == other.active + && audioLocalMuted == other.audioLocalMuted + && audioModeratorMuted == other.audioModeratorMuted && avatar == other.avatar + && bestName == other.bestName && isContact == other.isContact + && islocal == other.islocal && videoMuted == other.videoMuted + && handRaised == other.handRaised; + } +}; + +class LIB_EXPORT CallParticipants : public QObject +{ + Q_OBJECT + +public: + CallParticipants(const VectorMapStringString& infos, + const QString& callId, + const NewCallModel& linked); + ~CallParticipants() {} + + /** + * @return The list of participants that can have a widget in the client + */ + QList<ParticipantInfos> getParticipants() const; + + /** + * Update the participants + */ + void update(const VectorMapStringString& infos); + + /** + * Update conference layout value + */ + void verifyLayout(); + + /** + * @param uri participant + * @return True if participant is a moderator + */ + bool checkModerator(const QString& uri) const; + + /** + * @return the conference layout + */ + call::Layout getLayout() const { return hostLayout_; } + + /** + * @param index participant index + * @return informations of the participant in index + */ + QJsonObject toQJsonObject(uint index) const; + +private: + /** + * Filter the participants that might appear for the end user + */ + void filterCandidates(const VectorMapStringString& infos); + + void removeParticipant(int index); + + void addParticipant(const ParticipantInfos& participant); + + // Participants in the conference + QMap<QString, ParticipantInfos> candidates_; + // Participants ordered + QMap<QString, ParticipantInfos> participants_; + QList<QString> validUris_; + int idx_ = 0; + + const NewCallModel& linked_; + + // Protects changes into the paticipants_ variable + mutable std::mutex participantsMtx_ {}; + // Protects calls to the update function + std::mutex updateMtx_ {}; + + const QString callId_; + call::Layout hostLayout_ = call::Layout::GRID; +}; +} // end namespace api +} // end namespace lrc +Q_DECLARE_METATYPE(lrc::api::CallParticipants*) diff --git a/src/libclient/api/chatview.h b/src/libclient/api/chatview.h new file mode 100644 index 0000000000000000000000000000000000000000..606ab8b78c103dc19c46b1250091fe3e5e7c34f2 --- /dev/null +++ b/src/libclient/api/chatview.h @@ -0,0 +1,35 @@ +/**************************************************************************** + * Copyright (C) 2020-2022 Savoir-faire Linux Inc. * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +// Qt +#include <QObject> +#include <QVariantMap> +#include <QString> + +namespace lrc { + +namespace api { + +namespace chatview { + +QVariantMap getTranslatedStrings(bool qwebview = true); + +} // namespace chatview +} // namespace api +} // namespace lrc diff --git a/src/libclient/api/contact.h b/src/libclient/api/contact.h new file mode 100644 index 0000000000000000000000000000000000000000..8aaa1a0b9550e78fa82fe7e70dc2d0b65eecf364 --- /dev/null +++ b/src/libclient/api/contact.h @@ -0,0 +1,50 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#include "profile.h" + +#include <QString> + +namespace lrc { + +namespace api { + +namespace contact { + +/** + * @var profileInfo + * @var registeredName + * @var isTrusted + * @var isPresent + * @var isBanned + */ +struct Info +{ + profile::Info profileInfo; + QString registeredName; + bool isTrusted = false; + bool isPresent = false; + bool isBanned = false; + QString conversationId {}; +}; + +} // namespace contact +} // namespace api +} // namespace lrc diff --git a/src/libclient/api/contactmodel.h b/src/libclient/api/contactmodel.h new file mode 100644 index 0000000000000000000000000000000000000000..a2f4b792645b3b172bb2f4ee4b0c5a873293a8ea --- /dev/null +++ b/src/libclient/api/contactmodel.h @@ -0,0 +1,200 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#include "typedefs.h" +#include "api/behaviorcontroller.h" + +#include <QObject> + +#include <memory> + +namespace lrc { + +class CallbacksHandler; +class Database; +class ContactModelPimpl; + +namespace api { + +namespace contact { +struct Info; +} +namespace account { +struct Info; +} +namespace datatransfer { +struct Info; +} +class NewAccountModel; +class ConversationModel; + +/** + * @brief Class that manages contact information associated to an account. + */ +class LIB_EXPORT ContactModel : public QObject +{ + Q_OBJECT +public: + using ContactInfoMap = QMap<QString, contact::Info>; + + const account::Info& owner; + + ContactModel(const account::Info& owner, + Database& db, + const CallbacksHandler& callbacksHandler, + const BehaviorController& behaviorController); + ~ContactModel(); + + /** + * Ask the daemon to add a contact. + * @param contactInfo + */ + void addContact(contact::Info contactInfo); + /** + * Add a pending item into the contact list + * @param contactUri + */ + void addToContacts(const QString& contactUri); + /** + * Ask the daemon to remove a contact. + * @param contactUri + * @param banned + */ + void removeContact(const QString& contactUri, bool banned = false); + /** + * get contact information. + * @param contactUri + * @return the contact::Info structure for a contact + * @throws out_of_range exception if can't find the contact + */ + const contact::Info getContact(const QString& contactUri) const; + ContactInfoMap getSearchResults() const; + + /** + * Retrieve when a contact is added + */ + time_t getAddedTs(const QString& contactUri) const; + /** + * get list of banned contacts. + * @return list of banned contacts uris as string + */ + const QList<QString>& getBannedContacts() const; + /** + * @return all contacts for this account. + */ + const ContactInfoMap& getAllContacts() const; + + void searchContact(const QString& query); + /** + * Send a text interaction to a contact over the Dht. + * @param contactUri + * @param body + * @return id from daemon + */ + uint64_t sendDhtMessage(const QString& uri, const QString& body) const; + /** + * Get best id for contact + * @param contactUri + */ + const QString bestIdForContact(const QString& contactUri) const; + /** + * Get best name for contact + * @param contactUri + */ + const QString bestNameForContact(const QString& contactUri) const; + + /** + * Get avatar from storage + * @param contactUri + */ + QString avatar(const QString& contactUri) const; + +Q_SIGNALS: + /** + * Connect this signal to know when this model was updated. + */ + void modelUpdated(const QString& uri) const; + /** + * Connect this signal to know when a contact was added. + * @param contactUri + */ + void contactAdded(const QString& contactUri) const; + /** + * Connect this signal to know when a contact request received + * @param contactUri + */ + void incomingContactRequest(const QString& contactUri) const; + /** + * Connect this signal to know when a pending contact was accepted. + * @param contactUri + */ + void pendingContactAccepted(const QString& contactUri) const; + /** + * Connect this signal to know when an account was removed. + * @param contactUri + */ + void contactRemoved(const QString& contactUri) const; + /** + * Connect this signal to know when a call is incoming. + * @param fromId peer profile uri + * @param callId incoming call id + */ + void incomingCall(const QString& from, const QString& callId) const; + /** + * Connect this signal to know when a text message arrives for this account + * @param accountId + * @param msgId Interaction's id + * @param from peer uri + * @param payloads content of the message + */ + void newAccountMessage(const QString& accountId, + const QString& from, + const QString& msgId, + const MapStringString& payloads) const; + /** + * Connect this signal to know when a file transfer interaction is incoming + * @param fileId Daemon's ID for incoming transfer + * @param transferInfo DataTransferInfo structure from daemon + */ + void newAccountTransfer(const QString& fileId, datatransfer::Info info) const; + /** + * Connect this signal to know when a contact is banned or unbanned + * @param contactUri + * @param banned whether contact was banned or unbanned + */ + void bannedStatusChanged(const QString& contactUri, bool banned) const; + /** + * Connect this signal to know when contact profile was updated. + * @param contactUri + */ + void profileUpdated(const QString& contactUri) const; + +private: + /** + * Get best id from contact info + * @param contactInfo + */ + const QString bestIdFromContactInfo(const contact::Info& contactInfo) const; + + std::unique_ptr<ContactModelPimpl> pimpl_; +}; +} // namespace api +} // namespace lrc +Q_DECLARE_METATYPE(lrc::api::ContactModel*) diff --git a/src/libclient/api/conversation.h b/src/libclient/api/conversation.h new file mode 100644 index 0000000000000000000000000000000000000000..4608b2017bcf27c911c1d91ea9666a7481269975 --- /dev/null +++ b/src/libclient/api/conversation.h @@ -0,0 +1,109 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#include "interaction.h" +#include "messagelistmodel.h" +#include "member.h" +#include "typedefs.h" + +#include <map> +#include <memory> +#include <vector> + +namespace lrc { + +namespace api { + +namespace conversation { +Q_NAMESPACE +Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") + +enum class Mode { ONE_TO_ONE, ADMIN_INVITES_ONLY, INVITES_ONLY, PUBLIC, NON_SWARM }; +Q_ENUM_NS(Mode) + +static inline Mode +to_mode(const int intMode) +{ + switch (intMode) { + case 0: + return Mode::ONE_TO_ONE; + case 1: + return Mode::ADMIN_INVITES_ONLY; + case 2: + return Mode::INVITES_ONLY; + case 3: + return Mode::PUBLIC; + case 4: + return Mode::NON_SWARM; + default: + return Mode::ONE_TO_ONE; + } +} + +struct Info +{ + Info() + : interactions(std::make_unique<MessageListModel>(nullptr)) + {} + Info(const Info& other) = delete; + Info(Info&& other) = default; + Info& operator=(const Info& other) = delete; + Info& operator=(Info&& other) = default; + + bool allMessagesLoaded = false; + QString uid = ""; + QString accountId; + QVector<member::Member> participants; + QString callId; + QString confId; + std::unique_ptr<MessageListModel> interactions; + QString lastMessageUid = 0; + QHash<QString, QString> parentsId; // pair messageid/parentid for messages without parent loaded + unsigned int unreadMessages = 0; + + QSet<QString> typers; + + MapStringString infos {}; + + QString getCallId() const { return confId.isEmpty() ? callId : confId; } + + inline bool isLegacy() const { return mode == Mode::NON_SWARM; } + inline bool isSwarm() const { return !isLegacy(); } + // for each contact we must have one non-swarm conversation or one active one-to-one + // conversation. Where active means peer did not leave the conversation. + inline bool isCoreDialog() const { return isLegacy() || mode == Mode::ONE_TO_ONE; }; + + inline QStringList participantsUris() const + { + QStringList result; + for (const auto& p : participants) + result.append(p.uri); + return result; + } + + Mode mode = Mode::NON_SWARM; + bool needsSyncing = false; + bool isRequest = false; + bool readOnly = false; +}; + +} // namespace conversation +} // namespace api +} // namespace lrc diff --git a/src/libclient/api/conversationmodel.h b/src/libclient/api/conversationmodel.h new file mode 100644 index 0000000000000000000000000000000000000000..e96c3f99bfbaaf8e73f26a3e4bcb1eacbfdbc11c --- /dev/null +++ b/src/libclient/api/conversationmodel.h @@ -0,0 +1,553 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#include "typedefs.h" + +#include "api/conversation.h" +#include "api/profile.h" +#include "api/datatransfer.h" +#include "containerview.h" + +#include <QObject> +#include <QVector> +#include <QMap> + +#include <memory> +#include <deque> + +namespace lrc { + +class CallbacksHandler; +class ConversationModelPimpl; +class Database; + +namespace api { +Q_NAMESPACE +Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") + +namespace account { +struct Info; +} +namespace interaction { +struct Info; +} + +class Lrc; +class BehaviorController; +class NewAccountModel; + +enum class ConferenceableItem { CALL, CONTACT }; +Q_ENUM_NS(ConferenceableItem) + +enum class FilterType { INVALID = -1, JAMI, SIP, REQUEST, COUNT__ }; +Q_ENUM_NS(FilterType) + +struct AccountConversation +{ + QString convId; + QString accountId; +}; + +/* + * vector of conversationId and accountId. + * for calls and contacts contain only one element + * for conferences contains multiple entries + */ +typedef QVector<QVector<AccountConversation>> ConferenceableValue; + +/** + * @brief Class that manages conversation informations. + */ +class LIB_EXPORT ConversationModel : public QObject +{ + Q_OBJECT +public: + using ConversationQueue = std::deque<conversation::Info>; + using ConversationQueueProxy = ContainerView<ConversationQueue>; + + const account::Info& owner; + + ConversationModel(const account::Info& owner, + Lrc& lrc, + Database& db, + const CallbacksHandler& callbacksHandler, + const api::BehaviorController& behaviorController); + ~ConversationModel(); + + void initConversations(); + + /** + * Get unfiltered underlying conversation data. This is intended to + * serve as the underlying data for QAbstractListModel based objects. + * The corresponding data mutation signals will need to be responded + * to with appropriate QAbstractListModel signal forwarding. + * @return raw conversation queue + */ + const ConversationQueue& getConversations() const; + + /** + * Get conversations which should be shown client side + * @return conversations filtered with the current filter + */ + const ConversationQueueProxy& allFilteredConversations() const; + + /** + * Get conversation for a given uid + * @param uid conversation uid + * @return reference to conversation info with given uid + */ + OptRef<conversation::Info> getConversationForUid(const QString& uid) const; + + /** + * Get conversation for a given peer uri + * @param uri peer uri + * @return reference to conversation info with given peer uri + */ + OptRef<conversation::Info> getConversationForPeerUri(const QString& uri) const; + + /** + * Get conversation for a given call id + * @param callId call id + * @return reference to conversation info with given call id + */ + OptRef<conversation::Info> getConversationForCallId(const QString& callId) const; + + /** + * Get conversations that could be added to conference + * @param current conversation id + * @param search name filter + * @return filtered conversations + */ + QMap<ConferenceableItem, ConferenceableValue> getConferenceableConversations( + const QString& convId, const QString& filter = {}) const; + /** + * Get a custom filtered set of conversations + * @return conversations filtered + */ + const ConversationQueueProxy& getFilteredConversations( + const FilterType& filter = FilterType::INVALID, + bool forceUpdate = false, + const bool includeBanned = false) const; + /** + * Get a custom filtered set of conversations from profile type + * @return conversations filtered + */ + const ConversationQueueProxy& getFilteredConversations( + const profile::Type& profileType = profile::Type::INVALID, + bool forceUpdate = false, + const bool includeBanned = false) const; + /** + * Get the conversation at row in the filtered conversations + * @param row + * @return a copy of the conversation + */ + OptRef<conversation::Info> filteredConversation(unsigned row) const; + /** + * Get the search results + * @return a searchResult + */ + const ConversationQueue& getAllSearchResults() const; + + /** + * Get the conversation at row in the search results + * @param row + * @return a copy of the conversation + */ + OptRef<conversation::Info> searchResultForRow(unsigned row) const; + + /** + * Update the searchResults + * @param new status + */ + void updateSearchStatus(const QString& status) const; + /** + * Emit a filterChanged signal to force the client to refresh the filter. For instance + * this is required when a contact was banned or un-banned. + */ + void refreshFilter(); + /** + * Make permanent a temporary contact or a pending request. + * Ensure that given conversation is stored permanently into the system. + * @param uid of the conversation to change. + * @exception std::out_of_range if uid doesn't correspond to an existing conversation + */ + void makePermanent(const QString& uid); + /** + * Remove a conversation and the contact if it's a dialog + * @param uid of the conversation + * @param banned if we want to ban the contact. + */ + void removeConversation(const QString& uid, bool banned = false); + /** + * Get the action wanted by the user when they click on the conversation + * @param uid of the conversation + */ + void selectConversation(const QString& uid) const; + /** + * Call contacts linked to this conversation + * @param uid of the conversation + */ + void placeCall(const QString& uid); + /** + * Perform an audio call with contacts linked to this conversation + * @param uid of the conversation + */ + void placeAudioOnlyCall(const QString& uid); + /** + * Send a message to the conversation + * @param uid of the conversation + * @param body of the message + * @param parentId id of parent message. Default is "" - last message in conversation. + */ + void sendMessage(const QString& uid, const QString& body, const QString& parentId = ""); + /** + * Modify the current filter (will change the result of getFilteredConversations) + * @param filter the new filter + */ + void setFilter(const QString& filter); + /** + * Modify the current filter (will change the result of getFilteredConversations) + * @param filter the new filter (example: SIP, RING, REQUEST) + */ + void setFilter(const FilterType& filter = FilterType::INVALID); + /** + * Join participants from A to B and vice-versa. + * @note conversations must be in a call. + * @param uidA uid of the conversation A + * @param uidB uid of the conversation B + */ + void joinConversations(const QString& uidA, const QString& uidB); + /** + * Clear the history of a conversation + * @param uid of the conversation + */ + void clearHistory(const QString& uid); + /** + * change the status of the interaction from UNREAD to READ + * @param convId, id of the conversation + * @param msgId, id of the interaction + */ + void setInteractionRead(const QString& convId, const QString& msgId); + /** + * Clears the unread text messages of a conversation + * @param convId, uid of the conversation + */ + void clearUnreadInteractions(const QString& convId); + /** + * clear all history + */ + void clearAllHistory(); + /** + * Clear one interaction from the history + * @param convId + * @param interactionId + */ + void clearInteractionFromConversation(const QString& convId, const QString& interactionId); + /** + * Clear the cache for interactions in the conversation + * @param convId + */ + void clearInteractionsCache(const QString& convId); + /** + * Retry to send a message. In fact, will delete the previous interaction and resend a new one. + * @param convId + * @param interactionId + */ + void retryInteraction(const QString& convId, const QString& interactionId); + /** + * @param convId + * @param interactionId + * @param participant uri + * @return whether the interaction is last displayed for the conversation + */ + bool isLastDisplayed(const QString& convId, + const QString& interactionId, + const QString participant); + /** + * delete obsolete history from the database + * @param days, number of days from today. Below this date, interactions will be deleted + */ + void deleteObsoleteHistory(int date); + + void sendFile(const QString& convUid, const QString& path, const QString& filename); + + void acceptTransfer(const QString& convUid, const QString& interactionId); + + void acceptTransfer(const QString& convUid, const QString& interactionId, const QString& path); + + void cancelTransfer(const QString& convUid, const QString& interactionId); + + void getTransferInfo(const QString& conversationId, + const QString& interactionId, + api::datatransfer::Info& info) const; + /** + * @param convUid, uid of the conversation + * @return the number of unread messages for the conversation + */ + int getNumberOfUnreadMessagesFor(const QString& convUid); + /** + * Send a composing status + * @param convUid conversation's id + * @param isComposing if is composing + */ + void setIsComposing(const QString& convUid, bool isComposing); + /** + * load messages for conversation + * @param conversationId conversation's id + * @param size number of messages should be loaded. Default 1 + * @return id for loading request. -1 if not loaded + */ + int loadConversationMessages(const QString& conversationId, const int size = 1); + /** + * accept request for conversation + * @param conversationId conversation's id + */ + void acceptConversationRequest(const QString& conversationId); + /** + * add member to conversation + * @param conversationId conversation's id + * @param memberId members's id + */ + void addConversationMember(const QString& conversationId, const QString& memberId); + /** + * remove member from conversation + * @param conversationId conversation's id + * @param memberId members's id + */ + void removeConversationMember(const QString& conversationId, const QString& memberId); + /** + * get conversation info + * @param conversationId conversation's id + * @return conversation info + */ + MapStringString getConversationInfos(const QString& conversationId); + /** + * create a new swarm conversation + * @param participants conversation's participants + * @param infos conversation's infos + */ + void createConversation(const VectorString& participants, const MapStringString& infos = {}); + /** + * update conversation info + * @param conversationId conversation's id + * @param info + */ + void updateConversationInfos(const QString& conversationId, MapStringString info); + + /** + * @return if conversations requests exists. + */ + bool hasPendingRequests() const; + /** + * @return number of conversations requests + */ + int pendingRequestCount() const; + /** + * @return number of conversations requests + unread + */ + int notificationsCount() const; + const VectorString peersForConversation(const QString& conversationId); + + // Presentation + + /** + * Get conversation title. This means the title to show in the smartlist + * @param conversationId + * @return the title to display + */ + QString title(const QString& conversationId) const; + /** + * Get conversation's description. + * @param conversationId + * @return the description to display + */ + QString description(const QString& conversationId) const; + /** + * Get conversation's avatar. + * @param conversationId + * @return the avatar to display + */ + QString avatar(const QString& conversationId) const; + + /** + * Get member's role in conversation + * @param conversationId + * @param memberUri + * @return role + */ + member::Role memberRole(const QString& conversationId, const QString& memberUri) const; + +Q_SIGNALS: + /** + * Emitted when a conversation receives a new interaction + * @param uid of conversation + * @param interactionId + * @param interactionInfo + */ + void newInteraction(const QString& uid, + QString& interactionId, + const interaction::Info& interactionInfo) const; + /** + * Emitted when an interaction got a new status + * @param convUid conversation which owns the interaction + * @param interactionId + * @param msg + */ + void interactionStatusUpdated(const QString& convUid, + const QString& interactionId, + const api::interaction::Info& msg) const; + /** + * Emitted when an interaction got removed from the conversation + * @param convUid conversation which owns the interaction + * @param interactionId + */ + void interactionRemoved(const QString& convUid, const QString& interactionId) const; + /** + * Emitted when user clear the history of a conversation + * @param uid + */ + void conversationCleared(const QString& uid) const; + /** + * Emitted when conversation's participant has been updated + * @param uid + */ + void conversationUpdated(const QString& uid) const; + /** + * Emitted when the conversations list is modified + */ + void modelChanged() const; + /** + * Emitted when filter has changed + */ + void filterChanged() const; + /** + * Emitted when a conversation has been added + * @param uid + */ + void newConversation(const QString& uid) const; + /** + * Emitted when a conversation has been removed + * @param uid + */ + void conversationRemoved(const QString& uid) const; + /** + * Emitted after all history were cleared + * @note the client must connect this signal to know when update the view of the list + */ + void allHistoryCleared() const; + /** + * Emitted at the end of slotContactAdded and at conversationReady for swarm conversation to + * notify that an existing conversation can be modified + * @param uid + */ + void conversationReady(QString uid, QString participantURI) const; + /** + * Emitted when a contact in a conversation is composing a message + * @param uid conversation's id + * @param contactUri contact's uri + * @param isComposing if contact is composing a message + */ + void composingStatusChanged(const QString& uid, + const QString& contactUri, + bool isComposing) const; + /** + * Emitted when last displayed interaction changed + * @param uid of conversation + * @param participant URI + * @param previousUid uid of a previous displayed interaction + * @param newdUid uid of a new displayed interaction + */ + void displayedInteractionChanged(const QString& uid, + const QString& participantURI, + const QString& previousUid, + const QString& newdUid) const; + + /** + * Emitted when search status changed + * @param status + */ + void searchStatusChanged(const QString& status) const; + /** + * Emitted when search result has been updated + */ + void searchResultUpdated() const; + /** + * Emitted when finish loading messages for conversation + * @param loadingRequestId loading request id + * @param conversationId conversation Id + */ + void conversationMessagesLoaded(uint32_t loadingRequestId, const QString& conversationId) const; + /** + * Emitted when new messages available. When messages loaded from loading request or + * receiving/sending new interactions + * @param accountId account id + * @param conversationId conversation Id + */ + void newMessagesAvailable(const QString& accountId, const QString& conversationId) const; + + /** + * Emitted when creation of conversation started, finished with success or finisfed with error + * @param accountId account id + * @param conversationId conversation Id, when conversation creation started conversationId = + * participantURI + * @param participantURI participant uri + * @param status 0 -started, 1 -created with success, -1 -error + */ + void creatingConversationEvent(const QString& accountId, + const QString& conversationId, + const QString& participantURI, + int status) const; + + /** + * The following signals are intended for QAbtractListModel compatibility + */ + + /*! + * Emitted before conversations are inserted into the underlying queue + * @param position The starting row of the insertion + * @param rows The number of items inserted + */ + void beginInsertRows(int position, int rows = 1) const; + + //! Emitted once insertion is complete + void endInsertRows() const; + + /*! + * Emitted before conversations are removed from the underlying queue + * @param position The starting row of the removal + * @param rows The number of items removed + */ + void beginRemoveRows(int position, int rows = 1) const; + + //! Emitted once removal is complete + void endRemoveRows() const; + + /** + * Emitted once a conversation has been updated + * @param position + */ + void dataChanged(int position) const; + +private: + std::unique_ptr<ConversationModelPimpl> pimpl_; +}; +} // namespace api +} // namespace lrc +Q_DECLARE_METATYPE(lrc::api::ConversationModel*) diff --git a/src/libclient/api/datatransfer.h b/src/libclient/api/datatransfer.h new file mode 100644 index 0000000000000000000000000000000000000000..fef2dd34d0fc98be8ed71ec4c88ee6ef50b33977 --- /dev/null +++ b/src/libclient/api/datatransfer.h @@ -0,0 +1,120 @@ +/**************************************************************************** + * Copyright (C) 2018-2022 Savoir-faire Linux Inc. * + * Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +// LRC +#include "typedefs.h" + +// std +#include <ctime> + +#include <QString> + +namespace lrc { +namespace api { + +namespace datatransfer { +Q_NAMESPACE +Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") + +enum class Status { + on_connection, // outgoing tx: wait for connection/acceptance, incoming tx: wait for local acceptance + on_progress, // connected, data transfer progress reporting + success, // transfer finished with success, all data sent + stop_by_peer, // error: transfer terminated by peer + stop_by_host, // eror: transfer terminated by local host + unjoinable_peer, // error: (outgoing only) peer connection failed + timeout_expired, // error: (outgoing only) peer awaiting too long, close turn socket + invalid_pathname, // error: (file transfer only) given file is not a valid + unsupported, // error: unable to do the transfer (generic error) + INVALID +}; +Q_ENUM_NS(Status) + +static inline const QString +to_string(const Status& status) +{ + switch (status) { + case Status::on_connection: + return "on_connection"; + case Status::on_progress: + return "on_progress"; + case Status::success: + return "success"; + case Status::stop_by_peer: + return "stop_by_peer"; + case Status::stop_by_host: + return "stop_by_host"; + case Status::unjoinable_peer: + return "unjoinable_peer"; + case Status::timeout_expired: + return "timeout_expired"; + case Status::invalid_pathname: + return "invalid_pathname"; + case Status::unsupported: + return "unsupported"; + case Status::INVALID: + default: + return "INVALID"; + } +} + +static inline Status +to_status(const QString& status) +{ + if (status == "on_connection") + return datatransfer::Status::on_connection; + else if (status == "on_progress") + return datatransfer::Status::on_progress; + else if (status == "success") + return datatransfer::Status::success; + else if (status == "stop_by_peer") + return datatransfer::Status::stop_by_peer; + else if (status == "stop_by_host") + return datatransfer::Status::stop_by_host; + else if (status == "unjoinable_peer") + return datatransfer::Status::unjoinable_peer; + else if (status == "timeout_expired") + return datatransfer::Status::timeout_expired; + else if (status == "invalid_pathname") + return datatransfer::Status::invalid_pathname; + else if (status == "unsupported") + return datatransfer::Status::unsupported; + else + return datatransfer::Status::INVALID; +} + +struct Info +{ + QString uid; ///< long-term and unique identifier (used for historic) + Status status; + bool isOutgoing; + std::size_t totalSize; + std::size_t progress; ///< if status >= on_progress, gives number of bytes tx/rx until now + QString path; + QString displayName; + QString accountId; + QString peerUri; + QString conversationId; + std::time_t timestamp = 0; +}; + +} // namespace datatransfer + +} // namespace api +} // namespace lrc diff --git a/src/libclient/api/datatransfermodel.h b/src/libclient/api/datatransfermodel.h new file mode 100644 index 0000000000000000000000000000000000000000..6ac0542b3c7d9bd36d994a27bd5362c51e4e0a8c --- /dev/null +++ b/src/libclient/api/datatransfermodel.h @@ -0,0 +1,115 @@ +/**************************************************************************** + * Copyright (C) 2018-2022 Savoir-faire Linux Inc. * + * Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#include "api/datatransfer.h" +#include "api/account.h" + +#include "typedefs.h" + +#include <QObject> + +#include <string> +#include <memory> +#include <ios> + +namespace lrc { + +class CallbacksHandler; +class Database; + +namespace api { + +class BehaviorController; + +namespace datatransfer { +class Info; +} // namespace datatransfer + +/** + * @brief Class that manages data transfer. + */ +class LIB_EXPORT DataTransferModel : public QObject +{ + Q_OBJECT +public: + DataTransferModel(); + ~DataTransferModel(); + + void sendFile(const QString& account_id, + const QString& peer_uri, + const QString& conversationId, + const QString& file_path, + const QString& display_name); + + void transferInfo(const QString& accountId, const QString& fileId, datatransfer::Info& lrc_info); + + void fileTransferInfo(const QString& accountId, + const QString& conversationId, + const QString& fileId, + QString& path, + qlonglong& total, + qlonglong& progress); + + QString accept(const QString& accountId, const QString& fileId, const QString& filePath = {}); + + void download(const QString& accountId, + const QString& convId, + const QString& interactionId, + const QString& fileId, + const QString& filePath = {}); + + void copyTo(const QString& accountId, + const QString& convId, + const QString& interactionId, + const QString& destPath, + const QString& displayName); + + void cancel(const QString& accountId, const QString& conversationId, const QString& fileId); + + void registerTransferId(const QString& fileId, const QString& interactionId); + + QString getInteractionIdFromFileId(const QString& fileId); + + QString getFileIdFromInteractionId(const QString& fileId); + + /** + * Creates APPDATA/received and return the path + */ + static QString createDefaultDirectory(); + +Q_SIGNALS: + /** + * Connect this signal to know when a data transfer is incoming. + */ + void incomingTransfer(api::datatransfer::Info dataTransferInfo); + + /** + * Connect this signal to know when an existing data transfer has changed of status. + * @param transfer_id unique identification of incoming data transfer. + * @param status reported status. + */ + void transferStatusChanged(const QString& uid, datatransfer::Status status); + +private: + class Impl; + std::unique_ptr<Impl> pimpl_; +}; +} // namespace api +} // namespace lrc +Q_DECLARE_METATYPE(lrc::api::DataTransferModel*) diff --git a/src/libclient/api/interaction.h b/src/libclient/api/interaction.h new file mode 100644 index 0000000000000000000000000000000000000000..3b32df0174ae107f5eef16f47e1626466f1940a7 --- /dev/null +++ b/src/libclient/api/interaction.h @@ -0,0 +1,316 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#include <QString> +#include <QObject> + +#include <ctime> +#include "typedefs.h" + +namespace lrc { + +namespace api { + +namespace interaction { +Q_NAMESPACE +Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") + +enum class Type { INVALID, INITIAL, TEXT, CALL, CONTACT, DATA_TRANSFER, MERGE, COUNT__ }; +Q_ENUM_NS(Type) + +static inline const QString +to_string(const Type& type) +{ + switch (type) { + case Type::TEXT: + return "TEXT"; + case Type::INITIAL: + return "INITIAL"; + case Type::CALL: + return "CALL"; + case Type::CONTACT: + return "CONTACT"; + case Type::DATA_TRANSFER: + return "DATA_TRANSFER"; + case Type::MERGE: + return "MERGE"; + case Type::INVALID: + case Type::COUNT__: + default: + return "INVALID"; + } +} + +static inline Type +to_type(const QString& type) +{ + if (type == "INITIAL" || type == "initial") + return interaction::Type::INITIAL; + else if (type == "TEXT" || type == "text/plain") + return interaction::Type::TEXT; + else if (type == "CALL" || type == "application/call-history+json") + return interaction::Type::CALL; + else if (type == "CONTACT" || type == "member") + return interaction::Type::CONTACT; + else if (type == "DATA_TRANSFER" || type == "application/data-transfer+json") + return interaction::Type::DATA_TRANSFER; + else if (type == "merge") + return interaction::Type::MERGE; + else + return interaction::Type::INVALID; +} + +enum class Status { + INVALID, + UNKNOWN, + SENDING, + FAILURE, + SUCCESS, + DISPLAYED, + TRANSFER_CREATED, + TRANSFER_ACCEPTED, + TRANSFER_CANCELED, + TRANSFER_ERROR, + TRANSFER_UNJOINABLE_PEER, + TRANSFER_ONGOING, + TRANSFER_AWAITING_PEER, + TRANSFER_AWAITING_HOST, + TRANSFER_TIMEOUT_EXPIRED, + TRANSFER_FINISHED, + COUNT__ +}; +Q_ENUM_NS(Status) + +static inline const QString +to_string(const Status& status) +{ + switch (status) { + case Status::UNKNOWN: + return "UNKNOWN"; + case Status::SENDING: + return "SENDING"; + case Status::FAILURE: + return "FAILURE"; + case Status::SUCCESS: + return "SUCCESS"; + case Status::DISPLAYED: + return "DISPLAYED"; + case Status::TRANSFER_CREATED: + return "TRANSFER_CREATED"; + case Status::TRANSFER_ACCEPTED: + return "TRANSFER_ACCEPTED"; + case Status::TRANSFER_CANCELED: + return "TRANSFER_CANCELED"; + case Status::TRANSFER_ERROR: + return "TRANSFER_ERROR"; + case Status::TRANSFER_UNJOINABLE_PEER: + return "TRANSFER_UNJOINABLE_PEER"; + case Status::TRANSFER_ONGOING: + return "TRANSFER_ONGOING"; + case Status::TRANSFER_AWAITING_HOST: + return "TRANSFER_AWAITING_HOST"; + case Status::TRANSFER_AWAITING_PEER: + return "TRANSFER_AWAITING_PEER"; + case Status::TRANSFER_TIMEOUT_EXPIRED: + return "TRANSFER_TIMEOUT_EXPIRED"; + case Status::TRANSFER_FINISHED: + return "TRANSFER_FINISHED"; + case Status::INVALID: + case Status::COUNT__: + default: + return "INVALID"; + } +} + +static inline Status +to_status(const QString& status) +{ + if (status == "UNKNOWN") + return Status::UNKNOWN; + else if (status == "SENDING") + return Status::SENDING; + else if (status == "FAILURE") + return Status::FAILURE; + else if (status == "SUCCESS") + return Status::SUCCESS; + else if (status == "DISPLAYED") + return Status::DISPLAYED; + else if (status == "TRANSFER_CREATED") + return Status::TRANSFER_CREATED; + else if (status == "TRANSFER_ACCEPTED") + return Status::TRANSFER_ACCEPTED; + else if (status == "TRANSFER_CANCELED") + return Status::TRANSFER_CANCELED; + else if (status == "TRANSFER_ERROR") + return Status::TRANSFER_ERROR; + else if (status == "TRANSFER_UNJOINABLE_PEER") + return Status::TRANSFER_UNJOINABLE_PEER; + else if (status == "TRANSFER_ONGOING") + return Status::TRANSFER_ONGOING; + else if (status == "TRANSFER_AWAITING_HOST") + return Status::TRANSFER_AWAITING_HOST; + else if (status == "TRANSFER_AWAITING_PEER") + return Status::TRANSFER_AWAITING_PEER; + else if (status == "TRANSFER_TIMEOUT_EXPIRED") + return Status::TRANSFER_TIMEOUT_EXPIRED; + else if (status == "TRANSFER_FINISHED") + return Status::TRANSFER_FINISHED; + else + return Status::INVALID; +} + +enum class ContactAction { ADD, JOIN, LEAVE, BANNED, UNBANNED, INVALID }; +Q_ENUM_NS(ContactAction) + +static inline const QString +to_string(const ContactAction& action) +{ + switch (action) { + case ContactAction::ADD: + return "ADD"; + case ContactAction::JOIN: + return "JOIN"; + case ContactAction::LEAVE: + return "LEAVE"; + case ContactAction::BANNED: + return "BANNED"; + case ContactAction::UNBANNED: + return "UNBANNED"; + case ContactAction::INVALID: + return {}; + } + return {}; +} + +static inline ContactAction +to_action(const QString& action) +{ + if (action == "add") + return ContactAction::ADD; + else if (action == "join") + return ContactAction::JOIN; + else if (action == "remove") + return ContactAction::LEAVE; + else if (action == "ban") + return ContactAction::BANNED; + else if (action == "unban") + return ContactAction::UNBANNED; + return ContactAction::INVALID; +} + +static inline QString +getContactInteractionString(const QString& authorUri, const ContactAction& action) +{ + switch (action) { + case ContactAction::ADD: + if (authorUri.isEmpty()) { + return QObject::tr("Contact added"); + } + return QObject::tr("%1 was invited to join").arg(authorUri); + case ContactAction::JOIN: + return QObject::tr("%1 joined").arg(authorUri); + case ContactAction::LEAVE: + return QObject::tr("%1 left").arg(authorUri); + case ContactAction::BANNED: + return QObject::tr("%1 was kicked").arg(authorUri); + case ContactAction::UNBANNED: + return QObject::tr("%1 was re-added").arg(authorUri); + case ContactAction::INVALID: + return {}; + } + return {}; +} + +/** + * @var authorUri + * @var body + * @var timestamp + * @var duration + * @var type + * @var status + * @var isRead + * @var commit + * @var linkPreviewInfo + * @var linkified + */ +struct Info +{ + QString authorUri; + QString body; + QString parentId = ""; + std::time_t timestamp = 0; + std::time_t duration = 0; + Type type = Type::INVALID; + Status status = Status::INVALID; + bool isRead = false; + MapStringString commit; + QVariantMap linkPreviewInfo = {}; + bool linkified = false; + + Info() {} + + Info(QString authorUri, + QString body, + std::time_t timestamp, + std::time_t duration, + Type type, + Status status, + bool isRead) + { + this->authorUri = authorUri; + this->body = body; + this->timestamp = timestamp; + this->duration = duration; + this->type = type; + this->status = status; + this->isRead = isRead; + } + + Info(const MapStringString& message, const QString& accountURI) + { + type = to_type(message["type"]); + if (type == Type::TEXT) { + body = message["body"]; + } + authorUri = accountURI == message["author"] ? "" : message["author"]; + timestamp = message["timestamp"].toInt(); + status = Status::SUCCESS; + parentId = message["linearizedParent"]; + isRead = false; + if (type == Type::CONTACT) { + authorUri = accountURI == message["uri"] ? "" : message["uri"]; + } else if (type == Type::INITIAL) { + body = QObject::tr("Swarm created"); + } else if (type == Type::CALL) { + duration = message["duration"].toInt() / 1000; + } + commit = message; + } +}; + +static inline bool +isOutgoing(const Info& interaction) +{ + return interaction.authorUri.isEmpty(); +} + +} // namespace interaction +} // namespace api +} // namespace lrc diff --git a/src/libclient/api/lrc.h b/src/libclient/api/lrc.h new file mode 100644 index 0000000000000000000000000000000000000000..a752be39be67569eb607132dd24148008de31863 --- /dev/null +++ b/src/libclient/api/lrc.h @@ -0,0 +1,132 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * Author : Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#include "typedefs.h" + +#include <memory> +#include <vector> +#include <atomic> + +namespace lrc { + +class LrcPimpl; + +namespace api { + +class BehaviorController; +class NewAccountModel; +class DataTransferModel; +class AVModel; +class PluginModel; + +class LIB_EXPORT Lrc +{ +public: + /** + * Construct an Lrc object and optionally invoke callbacks + * to control ui informing the user of a possibly lengthy + * migration process. + * @param willMigrateCb + * @param didMigrateCb + */ + Lrc(MigrationCb willMigrateCb = {}, MigrationCb didMigrateCb = {}, bool muteDring = false); + ~Lrc(); + /** + * get a reference on account model. + * @return a NewAccountModel&. + */ + NewAccountModel& getAccountModel() const; + /** + * get a reference on the behavior controller. + * @return a BehaviorController&. + */ + BehaviorController& getBehaviorController() const; + /** + * get a reference on the audio-video controller. + * @return a AVModel&. + */ + AVModel& getAVModel() const; + + /** + * get a reference on the PLUGIN controller. + * @return a PluginModel&. + */ + PluginModel& getPluginModel() const; + + /** + * Inform the daemon that the connectivity changed + */ + void connectivityChanged() const; + + /** + * Test connection with daemon + */ + static bool isConnected(); + /** + * Can communicate with the daemon via dbus + */ + static bool dbusIsValid(); + /** + * Connect to debugMessageReceived signal + */ + void subscribeToDebugReceived(); + + /** + * Helper: get active call list from daemon + */ + static VectorString activeCalls(); + + /** + * Close all active calls and conferences + */ + void hangupCallsAndConferences(); + + /** + * Helper: get call list from daemon + */ + static VectorString getCalls(); + + /** + * Helper: get conference list from daemon + */ + static VectorString getConferences(const QString& accountId = ""); + + /** + * Preference + */ + static std::atomic_bool holdConferences; + + /** + * If cache contact's avatar or reload + */ + static std::atomic_bool cacheAvatars; + + /** + * Make monitor continous or discrete + */ + static void monitor(bool continous); + +private: + std::unique_ptr<LrcPimpl> lrcPimpl_; +}; + +} // namespace api +} // namespace lrc diff --git a/src/libclient/api/member.h b/src/libclient/api/member.h new file mode 100644 index 0000000000000000000000000000000000000000..91fe42e06fc1641d02aa8b78b8a77404a3ac08a8 --- /dev/null +++ b/src/libclient/api/member.h @@ -0,0 +1,61 @@ +/**************************************************************************** + * Copyright (C) 2021 Savoir-faire Linux Inc. * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#include "typedefs.h" + +#include <map> +#include <memory> +#include <vector> + +namespace lrc { + +namespace api { + +namespace member { +Q_NAMESPACE +Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") + +enum class Role { ADMIN, MEMBER, INVITED, BANNED, LEFT }; +Q_ENUM_NS(Role) + +static inline Role +to_role(const QString& roleStr) +{ + if (roleStr == "admin") + return Role::ADMIN; + if (roleStr == "member") + return Role::MEMBER; + if (roleStr == "invited") + return Role::INVITED; + if (roleStr == "banned") + return Role::BANNED; + if (roleStr == "left") + return Role::LEFT; + return Role::MEMBER; +} + +struct Member +{ + QString uri = ""; + Role role = Role::MEMBER; +}; + +} // namespace member +} // namespace api +} // namespace lrc diff --git a/src/libclient/api/newaccountmodel.h b/src/libclient/api/newaccountmodel.h new file mode 100644 index 0000000000000000000000000000000000000000..743130d2b126b837b02fd43cba10136732bc3dcc --- /dev/null +++ b/src/libclient/api/newaccountmodel.h @@ -0,0 +1,342 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#include "typedefs.h" +#include "api/account.h" + +#include <QObject> + +#include <vector> +#include <map> +#include <memory> +#include <string> +#include <mutex> +#include <condition_variable> + +namespace lrc { + +class CallbacksHandler; +class Database; +class NewAccountModelPimpl; + +namespace api { + +class Lrc; +class BehaviorController; + +/** + * @brief Class that manages account information. + */ +class LIB_EXPORT NewAccountModel : public QObject +{ + Q_OBJECT + Q_PROPERTY(QString downloadDirectory_qml MEMBER downloadDirectory) +public: + NewAccountModel(Lrc& lrc, + const CallbacksHandler& callbackHandler, + const api::BehaviorController& behaviorController, + MigrationCb& willMigrateCb, + MigrationCb& didMigrateCb); + + ~NewAccountModel(); + /** + * @return a list of all acountId. + */ + Q_INVOKABLE QStringList getAccountList() const; + /** + * get account informations associated to an accountId. + * @param accountId. + * @return a const account::Info& structure. + */ + const account::Info& getAccountInfo(const QString& accountId) const; + /** + * flag account corresponding to passed id as freeable. + */ + void flagFreeable(const QString& accountId) const; + + /** + * Used when images < 20 Mb are automatically accepted and downloaded + * Should contains the full directory with the end marker (/ on linux for example) + */ + QString downloadDirectory; + /** + * Accept transfer from untrusted contacts + */ + bool autoTransferFromUntrusted {false}; + /** + * Accept transfer from trusted contacts + */ + bool autoTransferFromTrusted {true}; + /** + * Automatically accept transfer under + */ + unsigned autoTransferSizeThreshold {20} /* Mb */; + /** + * set account enable/disable, save config and do unregister for account + * @param accountId. + * @param enabled. + */ + Q_INVOKABLE void setAccountEnabled(const QString& accountID, bool enabled) const; + /** + * saves account config to .yml + * @param accountId. + * @param reference to the confProperties + */ + void setAccountConfig(const QString& accountID, + const account::ConfProperties_t& confProperties) const; + /** + * gets a copy of the accounts config + * @param accountId. + * @return an account::Info::ConfProperties_t structure. + */ + account::ConfProperties_t getAccountConfig(const QString& accountId) const; + /** + * Call exportToFile from the daemon + * @param accountId + * @param path destination + * @param password + * @return if the file is exported with success + */ + Q_INVOKABLE bool exportToFile(const QString& accountId, + const QString& path, + const QString& password = {}) const; + /** + * Call exportOnRing from the daemon + * @param accountId + * @param password + * @return if the export is initialized + */ + Q_INVOKABLE bool exportOnRing(const QString& accountId, const QString& password) const; + /** + * Call removeAccount from the daemon + * @param accountId to remove + * @note will emit accountRemoved + */ + Q_INVOKABLE void removeAccount(const QString& accountId) const; + /** + * Call changeAccountPassword from the daemon + * @param accountId + * @param currentPassword + * @param newPassword + * @return if the password has been changed + */ + bool changeAccountPassword(const QString& accountId, + const QString& currentPassword, + const QString& newPassword) const; + /** + * Change the avatar of an account + * @param accountId + * @param avatar + * @throws out_of_range exception if account is not found + */ + void setAvatar(const QString& accountId, const QString& avatar); + /** + * Change the alias of an account + * @param accountId + * @param alias + * @throws out_of_range exception if account is not found + */ + void setAlias(const QString& accountId, const QString& alias); + /** + * Try to register a name + * @param accountId + * @param password + * @param username + * @return if operation started + */ + Q_INVOKABLE bool registerName(const QString& accountId, + const QString& password, + const QString& username); + /** + * Connect to JAMS to retrieve the account + * @param username + * @param password + * @param serverUri + * @param config + * @return the account id + */ + static QString connectToAccountManager(const QString& username, + const QString& password, + const QString& serverUri, + const MapStringString& config = MapStringString()); + /** + * Create a new Ring or SIP account + * @param type determine if the new account will be a Ring account or a SIP one + * @param displayName + * @param username + * @param archivePath + * @param password of the archive (unused for SIP) + * @param pin of the archive (unused for SIP) + * @param uri of the account (for SIP) + * @param config + * @return the created account + */ + static QString createNewAccount(profile::Type type, + const QString& displayName = "", + const QString& archivePath = "", + const QString& password = "", + const QString& pin = "", + const QString& uri = "", + const MapStringString& config = MapStringString()); + /** + * Set an account to the first position + */ + void setTopAccount(const QString& accountId); + /** + * Get the vCard for an account + * @param id + * @return vcard of the account + */ + QString accountVCard(const QString& accountId, bool compressImage = true) const; + /** + * Get the best name for an account + * @param id + * @return best name of the account + */ + const QString bestNameForAccount(const QString& accountID); + /** + * Get the best id for an account + * @param id + * @return best id of the account + */ + const QString bestIdForAccount(const QString& accountID); + /** + * Add/remove default moderator + * @param accountID + * @param peerURI + * @param state + */ + void setDefaultModerator(const QString& accountID, const QString& peerURI, const bool& state); + /** + * Get default moderators for an account + * @param accountID + * @return default moderators for the account + */ + QStringList getDefaultModerators(const QString& accountID); + /** + * Enable/disable local moderators + * @param accountID + * @param isModEnabled + */ + void enableLocalModerators(const QString& accountID, const bool& isModEnabled); + /** + * Get local moderators state + * @param accountID + * @return if local moderator is enabled + */ + bool isLocalModeratorsEnabled(const QString& accountID); + /** + * Enable/disable all moderators + * @param accountID + * @param allModerators + */ + void setAllModerators(const QString& accountID, const bool& allModerators); + /** + * Get all moderators state + * @param accountID + * @return if all moderator is enabled + */ + bool isAllModerators(const QString& accountID); + /** + * Get notifications count across accounts + */ + int notificationsCount() const; + /** + * Retrieve account's avatar + */ + QString avatar(const QString& accountId) const; + +Q_SIGNALS: + /** + * Connect this signal to know when an invalid account is here + * @param accountID + */ + void invalidAccountDetected(const QString& accountID); + /** + * Connect this signal to know when the status of an account has changed. + * @param accountID + */ + void accountStatusChanged(const QString& accountID); + /** + * Connect this signal to know when the details of an account has changed. + * @param accountID + */ + void accountDetailsChanged(const QString& accountID); + /** + * Connect this signal to know when an account was added. + * @param accountID + */ + void accountAdded(const QString& accountID); + /** + * Connect this signal to know when an account was removed. + * @param accountID + */ + void accountRemoved(const QString& accountID); + /** + * Connect this signal to know when an account was updated. + * @param accountID + */ + void profileUpdated(const QString& accountID); + + /** + * Connect this signal to know when an account is exported on the DHT + * @param accountID + * @param status + * @param pin + */ + void exportOnRingEnded(const QString& accountID, + account::ExportOnRingStatus status, + const QString& pin); + + /** + * Name registration has ended + * @param accountId + * @param status + * @param name + */ + void nameRegistrationEnded(const QString& accountId, + account::RegisterNameStatus status, + const QString& name); + + /** + * Name registration has been found + * @param accountId + * @param status + * @param name + */ + void registeredNameFound(const QString& accountId, + account::LookupStatus status, + const QString& address, + const QString& name); + + /** + * Migration has finished + * @param accountId + * @param ok + */ + void migrationEnded(const QString& accountId, bool ok); + +private: + std::unique_ptr<NewAccountModelPimpl> pimpl_; +}; +} // namespace api +} // namespace lrc +Q_DECLARE_METATYPE(lrc::api::NewAccountModel*) diff --git a/src/libclient/api/newcallmodel.h b/src/libclient/api/newcallmodel.h new file mode 100644 index 0000000000000000000000000000000000000000..363bdc5f224e27cd7f30c68884b97ed68a044b1a --- /dev/null +++ b/src/libclient/api/newcallmodel.h @@ -0,0 +1,507 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#include "api/behaviorcontroller.h" +#include "api/call.h" +#include "api/account.h" +#include "api/video.h" +#include "typedefs.h" + +#include <QObject> + +#include <memory> +#include <map> + +namespace lrc { + +class CallbacksHandler; +class NewCallModelPimpl; + +namespace api { + +namespace account { +struct Info; +} +namespace call { +struct Info; + +struct PendingConferenceeInfo +{ + QString uri; + QString callId; + QString callIdToJoin; +}; +} // namespace call +class NewAccountModel; +class CallParticipants; + +/** + * @brief Class that manages call informations. + */ +class LIB_EXPORT NewCallModel : public QObject +{ + Q_OBJECT + +public: + using CallInfoMap = std::map<QString, std::shared_ptr<call::Info>>; + using CallParticipantsModelMap = std::map<QString, std::shared_ptr<CallParticipants>>; + + const account::Info& owner; + + enum class Media { NONE, AUDIO, VIDEO }; + enum class MediaRequestType { FILESHARING, SCREENSHARING, CAMERA }; + + NewCallModel(const account::Info& owner, + Lrc& lrc, + const CallbacksHandler& callbacksHandler, + const BehaviorController& behaviorController); + ~NewCallModel(); + + /** + * Create a new call with a contact + * @param uri of the contact to call + * @param isAudioOnly, set to false by default + * @return the call uid created. Empty string is returned if call couldn't be created. + */ + QString createCall(const QString& uri, + bool isAudioOnly = false, + VectorMapStringString mediaList = {}); + + /** + * Request a media change in a ongoing call. + * @param accountId + * @param callId + * @param mediaLabel label of media to be changed + * @param source + * @param type + * @param mute + */ + void requestMediaChange(const QString& callId, + const QString& mediaLabel, + const QString& source, + MediaRequestType type, + bool mute); + + /** + * Get the call from its call id + * @param uid + * @return the callInfo + * @throw out_of_range exception if not found + */ + const call::Info& getCall(const QString& uid) const; + + /** + * Get the call participantsInfos from its call id + * @param callId + * @return the call participantsInfos + * @throw out_of_range exception if not found + */ + const CallParticipants& getParticipantsInfos(const QString& callId); + + /** + * Get the call from the peer uri + * @param uri + * @param notOver search for a non finished call + * @return the callInfo + * @throw out_of_range exception if not found + */ + const call::Info& getCallFromURI(const QString& uri, bool notOver = false) const; + + /** + * Get conference from a peer uri + * @param uri + * @return the callInfo + * @throw out_of_range exception if not found + */ + const call::Info& getConferenceFromURI(const QString& uri) const; + + /** + * Helper: get subcalls list for a conference from daemon + */ + VectorString getConferenceSubcalls(const QString& cid); + + /** + * @param callId to test + * @return true if callId is presend else false. + */ + bool hasCall(const QString& callId) const; + + /** + * Send a text message to a SIP call + * @param callId + * @param body of the message + */ + void sendSipMessage(const QString& callId, const QString& body) const; + + /** + * Accept a call + * @param callId + */ + void accept(const QString& callId) const; + + /** + * Hang up a call + * @param callId + */ + void hangUp(const QString& callId) const; + + /** + * Refuse a call + * @param callId + */ + void refuse(const QString& callId) const; + + /** + * Toggle audio record on a call + * @param callId + */ + void toggleAudioRecord(const QString& callId) const; + + /** + * Play DTMF in a call + * @param callId + * @param value to play + */ + void playDTMF(const QString& callId, const QString& value) const; + + /** + * Toggle pause on a call. + * @warn only use this function for SIP calls + * @param callId + */ + void togglePause(const QString& callId) const; + + /** + * @deprecated Use requestMediaChange instead + * Toggle a media on a call + * @param callId + * @param media {AUDIO, VIDEO} + */ + void toggleMedia(const QString& callId, const NewCallModel::Media media); + + /** + * Not implemented yet + */ + void setQuality(const QString& callId, const double quality) const; + + /** + * Blind transfer. Directly transfer a call to a sip number + * @param callId: the call to transfer + * @param to: the sip number (for example: "sip:1412") + */ + void transfer(const QString& callId, const QString& to) const; + + /** + * Perform an attended. Transfer a call to another call + * @param callIdSrc: the call to transfer + * @param callIdDest: the destination's call + */ + void transferToCall(const QString& callIdSrc, const QString& callIdDest) const; + + /** + * Create a conference from 2 calls. + * @param callIdA uid of the call A + * @param callIdB uid of the call B + */ + void joinCalls(const QString& callIdA, const QString& callIdB) const; + + /** + * Call a participant and add it to a call + * @param uri URI of the participant + * @param callId Call receiving the participant + * @param audioOnly If the call is audio only + * @return id for a new call + */ + QString callAndAddParticipant(const QString uri, const QString& callId, bool audioOnly); + + /** + * Not implemented yet + */ + void removeParticipant(const QString& callId, const QString& participant) const; + + /** + * @param callId + * @return a human readable call duration (M:ss) + */ + QString getFormattedCallDuration(const QString& callId) const; + + /** + * Get if a call is recording + * @param callId + * @return true if the call is recording else false + */ + bool isRecording(const QString& callId) const; + /** + * Extract Status Message From Status Map + * @param statusCode + * @return status message + */ + static QString getSIPCallStatusString(const short& statusCode); + + /** + * Set a call as the current call (hold other calls) + */ + void setCurrentCall(const QString& callId) const; + + /** + * Update call mediaList to be used in the call answering + * + * @param callId + * @param acceptVideo + */ + void updateCallMediaList(const QString& callId, bool acceptVideo); + + /** + * Change the conference layout + */ + void setConferenceLayout(const QString& confId, const call::Layout& layout); + + /** + * Set the shown participant + * @param confId The call to change + * @param participant Use contact URI + */ + void setActiveParticipant(const QString& confId, const QString& participant); + + /** + * Check if a participant is a moderator or not + * @param confId The conference to check + * @param uri Uri of the participant to check (if empty, check current account) + * @return if moderator + */ + bool isModerator(const QString& confId, const QString& uri = ""); + + /** + * Set/unset a moderator + * @param confId The conference to change + * @param peerId Uri of the participant to change + * @param state State of the change (true set moderator / false unset moderator) + */ + void setModerator(const QString& confId, const QString& peerId, const bool& state); + + /** + * Check if a participant has raised hand + * @param confId The conference to check + * @param uri Uri of the participant to check (if empty, check current account) + * @return if hand is raised + */ + bool isHandRaised(const QString& confId, const QString& uri = "") noexcept; + + /** + * Set/unset a moderator + * @param confId The conference to change + * @param peerId Uri of the participant to change + * @param state State of the change (true set hand raised / false unset hand raised) + */ + void setHandRaised(const QString& accountId, + const QString& confId, + const QString& peerId, + bool state); + + /** + * Mute/unmute participant + * @param confId The conference to change + * @param peerId Uri of the participant to mute + * @param state State of the change (true mute participant / false unmute participant) + */ + void muteParticipant(const QString& confId, const QString& peerId, const bool& state); + + /** + * Hangup participant + * @param confId The call to change + * @param participant Use contact URI + */ + void hangupParticipant(const QString& confId, const QString& participant); + + /** + * Check if a call is a conference or not + * @param callId The call to check + * @return if conference + */ + bool isConferenceHost(const QString& callId); + + /** + * Get the list of lists of pending conferencees callId , contact uri, and join callId + * @return pending conferencees + */ + const QList<call::PendingConferenceeInfo>& getPendingConferencees(); + + /** + * Get informations on the rendered device + * @param call_id linked call to the renderer + * @return the device rendered + */ + video::RenderedDevice getCurrentRenderedDevice(const QString& call_id) const; + + /** + * @deprecated + * Render a file to the call id specified + * @param uri the path of the file + * @param callId + * @note callId can be omitted to switch the input of the local recorder + */ + void setInputFile(const QString& uri, const QString& callId = {}); + /** + * Change the current device rendered for the call id specified + * @param id of the camera + * @param callId + * @note renders a black frame if device not found or empty + * @note callId can be omitted to switch the input of the local recorder + */ + void switchInputTo(const QString& id, const QString& callId = {}); + /** + * Get the current display resource string + * @param idx of the display + * @param x top left of the area + * @param y top up of the area + * @param w width of the area + * @param h height of the area + */ + QString getDisplay(int idx, int x, int y, int w, int h); + /** + * Get the current window resource string + * @param windowId + */ + QString getDisplay(const QString& windowId); + /** + * @deprecated + * Render the current display to the call id specified + * @param idx of the display + * @param x top left of the area + * @param y top up of the area + * @param w width of the area + * @param h height of the area + * @param callId + * @note callId can be omitted to switch the input of the local recorder + */ + void setDisplay(int idx, int x, int y, int w, int h, const QString& callId = {}); +Q_SIGNALS: + + /** + * Emitted when a participant video is added to a conference + * @param callId + * @param index + */ + void participantAdded(const QString& callId, int index) const; + + /** + * Emitted when a participant video is removed from a conference + * @param callId + * @param index + */ + void participantRemoved(const QString& callId, int index) const; + + /** + * Emitted when, in a conference, participant parameters are changed + * @param callId + * @param index + */ + void participantUpdated(const QString& callId, int index) const; + + /** + * Emitted when a call state changes + * @param callId + */ + void callStatusChanged(const QString& callId, int code) const; + /** + * Emitted when the rendered image changed + * @param confId + */ + void onParticipantsChanged(const QString& confId) const; + /** + * Emitted when a call starts + * @param callId + */ + void callStarted(const QString& callId) const; + /** + * Emitted when a call is over + * @param callId + */ + void callEnded(const QString& callId) const; + /** + * Emitted when a call is incoming + * @param callId + * @param fromId the peer uri + * @param displayname + */ + void newIncomingCall(const QString& fromId, + const QString& callId, + const QString& displayname) const; + /** + * Emitted when a call is added to a conference + * @param callId + * @param confId + */ + void callAddedToConference(const QString& callId, const QString& confId) const; + + /** + * Emitted when a voice mail notice arrives + * @param accountId + * @param newCount + * @param oldCount + * @param urgentCount + */ + void voiceMailNotify(const QString& accountId, + int newCount, + int oldCount, + int urgentCount) const; + + /** + * Listen from CallbacksHandler when the peer start recording + * @param callId + * @param contactId + * @param peerName + * @param state the new state + */ + void remoteRecordingChanged(const QString& callId, + const QSet<QString>& peerRec, + bool state) const; + + /*! + * Emitted before new pending conferences are inserted into the underlying list + * @param position The starting row of the insertion + * @param rows The number of items inserted + */ + void beginInsertPendingConferenceesRows(int position, int rows = 1) const; + + //! Emitted once the insertion of new pending conferences is complete + void endInsertPendingConferenceesRows() const; + + /*! + * Emitted before new pending conferences are removed from the underlying list + * @param position The starting row of the removal + * @param rows The number of items removed + */ + void beginRemovePendingConferenceesRows(int position, int rows = 1) const; + + //! Emitted once the removal of new pending conferences is complete + void endRemovePendingConferenceesRows() const; + + /** + * Emitted callInfosChanged + */ + void callInfosChanged(const QString& accountId, const QString& callId) const; + +private: + std::unique_ptr<NewCallModelPimpl> pimpl_; +}; +} // namespace api +} // namespace lrc +Q_DECLARE_METATYPE(lrc::api::NewCallModel*) diff --git a/src/libclient/api/newcodecmodel.h b/src/libclient/api/newcodecmodel.h new file mode 100644 index 0000000000000000000000000000000000000000..193c083a5a7ea267e068cf59e75d0e05906918d4 --- /dev/null +++ b/src/libclient/api/newcodecmodel.h @@ -0,0 +1,122 @@ +/**************************************************************************** + * Copyright (C) 2018-2022 Savoir-faire Linux Inc. * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#include "api/account.h" +#include "typedefs.h" + +#include <QObject> +#include <QList> + +#include <memory> + +namespace lrc { + +class CallbacksHandler; +class NewCodecModelPimpl; + +namespace api { + +namespace account { +struct Info; +} + +struct Codec +{ + unsigned int id; + bool enabled; + QString name; + QString samplerate; + QString bitrate; + QString min_bitrate; + QString max_bitrate; + QString type; + QString quality; + QString min_quality; + QString max_quality; + bool auto_quality_enabled; +}; + +/** + * @brief Class that manages ring devices for an account + */ +class LIB_EXPORT NewCodecModel : public QObject +{ + Q_OBJECT + +public: + const account::Info& owner; + + NewCodecModel(const account::Info& owner, const CallbacksHandler& callbacksHandler); + ~NewCodecModel(); + + /** + * @return audio codecs for the account + */ + QList<Codec> getAudioCodecs() const; + /** + * @return video codecs for the account + */ + QList<Codec> getVideoCodecs() const; + /** + * Set a higher priority to a codec + * @param codecId + * @param isVideo + */ + void increasePriority(const unsigned int& codecid, bool isVideo); + /** + * Set a lower priority to a codec + * @param codecId + * @param isVideo + */ + void decreasePriority(const unsigned int& codecid, bool isVideo); + /** + * Enable a codec + * @param codecId + * @param enabled true if enabled else false + * @return if codecId is the only codec impacted + */ + bool enable(const unsigned int& codecid, bool enabled); + /** + * Enable/Disable auto quality for this codec + * @param codecId + * @param on true if enabled else false + * @return + */ + void autoQuality(const unsigned int& codecid, bool on); + /** + * Change wanted quality + * @param codecId + * @param quality + * @return + */ + void quality(const unsigned int& codecid, double quality); + /** + * Change wanted bitrate + * @param codecId + * @param bitrate + * @return + */ + void bitrate(const unsigned int& codecid, double bitrate); + +private: + std::unique_ptr<NewCodecModelPimpl> pimpl_; +}; +} // namespace api +} // namespace lrc +Q_DECLARE_METATYPE(lrc::api::NewCodecModel*) diff --git a/src/libclient/api/newdevicemodel.h b/src/libclient/api/newdevicemodel.h new file mode 100644 index 0000000000000000000000000000000000000000..7f95b014681aa6c95e2678f3a4f16289cb3162cb --- /dev/null +++ b/src/libclient/api/newdevicemodel.h @@ -0,0 +1,116 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#include "api/account.h" +#include "typedefs.h" + +#include <QObject> + +#include <memory> +#include <string> +#include <list> + +namespace lrc { + +class CallbacksHandler; +class NewDeviceModelPimpl; + +namespace api { + +namespace account { +struct Info; +} + +struct Device +{ + QString id = ""; + QString name = ""; + bool isCurrent = false; +}; + +/** + * @brief Class that manages ring devices for an account + */ +class LIB_EXPORT NewDeviceModel : public QObject +{ + Q_OBJECT + +public: + /** + * Used by deviceRevoked's status + */ + enum class Status { SUCCESS = 0, WRONG_PASSWORD = 1, UNKNOWN_DEVICE = 2 }; + const account::Info& owner; + + NewDeviceModel(const account::Info& owner, const CallbacksHandler& callbacksHandler); + ~NewDeviceModel(); + + /** + * Get ring devices of an account + * @return a copy of current devices + */ + QList<Device> getAllDevices() const; + + /** + * Retrieve a device by its id + * @param id of the device + * @return the device if found else a device with a null id + */ + Device getDevice(const QString& id) const; + + /** + * Revoke a ring device + * @param id of the device to revoke + * @param password of the account's archive + * @note will emit deviceRevoked when finished + */ + Q_INVOKABLE void revokeDevice(const QString& id, const QString& password); + + /** + * Change the name of the current device + * @param newName + * @note will emit deviceUpdated when finished + * @note ring can't change the name of another device + */ + void setCurrentDeviceName(const QString& newName); + +Q_SIGNALS: + /** + * Link to this signal to know when a new device is added + * @param id added device + */ + void deviceAdded(const QString& id) const; + /** + * Link to this signal to know when a device is removed + * @param id removed device + * @param Status (SUCCESS, WRONG_PASSWORD, UNKNOWN_DEVICE) + */ + void deviceRevoked(const QString& id, const Status status) const; + /** + * Link to this signal when a device get a new name + * @param id + */ + void deviceUpdated(const QString& id) const; + +private: + std::unique_ptr<NewDeviceModelPimpl> pimpl_; +}; +} // namespace api +} // namespace lrc +Q_DECLARE_METATYPE(lrc::api::NewDeviceModel*) diff --git a/src/libclient/api/peerdiscoverymodel.h b/src/libclient/api/peerdiscoverymodel.h new file mode 100644 index 0000000000000000000000000000000000000000..a2049d6e5ee7d04b0d6769923f2816c46142ac3b --- /dev/null +++ b/src/libclient/api/peerdiscoverymodel.h @@ -0,0 +1,73 @@ +/**************************************************************************** + * Copyright (C) 2019-2022 Savoir-faire Linux Inc. * + * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#pragma once + +// Lrc +#include "typedefs.h" + +// Qt +#include <QObject> + +// std +#include <vector> +#include <map> +#include <memory> + +namespace lrc { + +class CallbacksHandler; +class PeerDiscoveryModelPimpl; + +namespace api { + +struct PeerContact +{ + std::string uri; + std::string displayName; +}; + +enum class PeerModelChanged { INSERT, REMOVE }; + +/** + * @brief Class that manages local peer discovery info + */ +class LIB_EXPORT PeerDiscoveryModel : public QObject +{ + Q_OBJECT +public: + PeerDiscoveryModel(const CallbacksHandler& callbackHandler, const QString& accountID); + ~PeerDiscoveryModel(); + /** + * get a map of discovered peers account + * @return a std::vector<PeerContact> + */ + std::vector<PeerContact> getNearbyPeers() const; + +Q_SIGNALS: + /** + * Connect this signal to know when the status of local peer discovery map changed. + */ + void modelChanged(const QString& contactUri, PeerModelChanged state, const QString& displayname); + +private: + std::unique_ptr<PeerDiscoveryModelPimpl> pimpl_; +}; +} // namespace api +} // namespace lrc +Q_DECLARE_METATYPE(lrc::api::PeerDiscoveryModel*) diff --git a/src/libclient/api/pluginmodel.h b/src/libclient/api/pluginmodel.h new file mode 100644 index 0000000000000000000000000000000000000000..6f5748524d793a6b1fce4e4a632111337c51dd02 --- /dev/null +++ b/src/libclient/api/pluginmodel.h @@ -0,0 +1,191 @@ +/*! + * Copyright (C) 2018-2022 Savoir-faire Linux Inc. + * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#pragma once + +// std +#include <memory> +#include <string> +#include <vector> + +// Qt +#include <qobject.h> + +// LRC +#include "typedefs.h" + +namespace lrc { + +namespace api { + +namespace plugin { +/** + * This class describes current plugin Details + */ +struct PluginDetails +{ + QString name = ""; + QString path = ""; + QString iconPath = ""; + bool loaded = false; +}; + +struct PluginHandlerDetails +{ + QString id = ""; + QString name = ""; + QString iconPath = ""; + QString pluginId = ""; +}; +} // namespace plugin + +class LIB_EXPORT PluginModel : public QObject +{ + Q_OBJECT +public: + PluginModel(); + ~PluginModel(); + + /** + * Enable/disable plugins + * @param if plugin enabled + */ + Q_INVOKABLE void setPluginsEnabled(bool enable); + + /** + * Get if plugins are enabled + * @return plugins enabled + */ + Q_INVOKABLE bool getPluginsEnabled() const; + + /** + * Get list of installed plugins + * @return plugins installed + */ + VectorString getInstalledPlugins() const; + + /** + * Get list of loaded plugins + * @return plugins loaded + */ + VectorString getLoadedPlugins() const; + + /** + * Get details of installed plugin + * @return plugin Details + */ + plugin::PluginDetails getPluginDetails(const QString& path); + + /** + * Install plugin + * @return true if plugin was succesfully installed + */ + Q_INVOKABLE bool installPlugin(const QString& jplPath, bool force); + + /** + * Uninstall plugin + * @return true if plugin was succesfully uninstalled + */ + Q_INVOKABLE bool uninstallPlugin(const QString& rootPath); + + /** + * Load plugin + * @return true if plugin was succesfully loaded + */ + Q_INVOKABLE bool loadPlugin(const QString& path); + + /** + * Unload plugin + * @return true if plugin was succesfully unloaded + */ + Q_INVOKABLE bool unloadPlugin(const QString& path); + + /** + * List all plugins Media Handlers + * @return List of all plugins Media Handlers + */ + VectorString getCallMediaHandlers() const; + + /** + * Toggle media handler + */ + Q_INVOKABLE void toggleCallMediaHandler(const QString& mediaHandlerId, + const QString& callId, + bool toggle); + + VectorString getChatHandlers() const; + + /** + * Toggle chat handler + */ + Q_INVOKABLE void toggleChatHandler(const QString& chatHandlerId, + const QString& accountId, + const QString& peerId, + bool toggle); + + /** + * Verify if there is an active plugin media handler + * @return Map with name and status + */ + VectorString getCallMediaHandlerStatus(const QString& callId); + + /** + * Get details of installed plugins media handlers + * @return Media Handler Details + */ + plugin::PluginHandlerDetails getCallMediaHandlerDetails(const QString& mediaHandlerId); + + VectorString getChatHandlerStatus(const QString& accountId, const QString& peerId); + + plugin::PluginHandlerDetails getChatHandlerDetails(const QString& chatHandlerId); + + /** + * Get preferences map of installed plugin + * @return Plugin preferences infos vector + */ + Q_INVOKABLE VectorMapStringString getPluginPreferences(const QString& path, + const QString& accountId); + + /** + * Modify preference of installed plugin + * @return true if preference was succesfully modified + */ + Q_INVOKABLE bool setPluginPreference(const QString& path, + const QString& accountId, + const QString& key, + const QString& value); + + /** + * Get preferences values of installed plugin + * @return Plugin preferences map + */ + MapStringString getPluginPreferencesValues(const QString& path, const QString& accountId); + + /** + * Reste preferences values of installed plugin to default values + * @return true if preference was succesfully reset + */ + Q_INVOKABLE bool resetPluginPreferencesValues(const QString& path, const QString& accountId); + +Q_SIGNALS: + void chatHandlerStatusUpdated(bool isVisible); + void modelUpdated(); +}; + +} // namespace api +} // namespace lrc +Q_DECLARE_METATYPE(lrc::api::PluginModel*) diff --git a/src/libclient/api/profile.h b/src/libclient/api/profile.h new file mode 100644 index 0000000000000000000000000000000000000000..5990bad55f7ec8200a2714b696ef6f42ea8cfc3a --- /dev/null +++ b/src/libclient/api/profile.h @@ -0,0 +1,85 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#include <QObject> +#include <QString> + +namespace lrc { + +namespace api { + +namespace profile { +Q_NAMESPACE +Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") + +enum class Type { INVALID, JAMI, SIP, PENDING, TEMPORARY, COUNT__ }; +Q_ENUM_NS(Type) + +static inline const QString +to_string(const Type& type) +{ + switch (type) { + case Type::JAMI: + return "JAMI"; + case Type::SIP: + return "SIP"; + case Type::PENDING: + return "PENDING"; + case Type::TEMPORARY: + return "TEMPORARY"; + case Type::INVALID: + case Type::COUNT__: + default: + return "INVALID"; + } +} + +static inline Type +to_type(const QString& type) +{ + if (type == "PENDING") + return Type::PENDING; + else if (type == "SIP") + return Type::SIP; + else if (type == "JAMI") + return Type::JAMI; + else if (type == "TEMPORARY") + return Type::TEMPORARY; + else + return Type::INVALID; +} + +/** + * @var uri + * @var avatar + * @var alias + * @var type + */ +struct Info +{ + QString uri = ""; + QString avatar = ""; + QString alias = ""; + Type type = Type::INVALID; +}; + +} // namespace profile +} // namespace api +} // namespace lrc diff --git a/src/libclient/api/video.h b/src/libclient/api/video.h new file mode 100644 index 0000000000000000000000000000000000000000..5d44c0241fd2b08277d274e0ffd4e8d457af89c4 --- /dev/null +++ b/src/libclient/api/video.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2018-2022 Savoir-faire Linux Inc. + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> + * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "typedefs.h" + +#include <QObject> +#include <QPair> + +#include <map> +#include <memory> +#include <string> +#include <vector> + +extern "C" { +#include <libavutil/frame.h> +} + +namespace lrc { +namespace api { +namespace video { +Q_NAMESPACE +Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") + +constexpr static const char PREVIEW_RENDERER_ID[] = "local"; + +using Channel = QString; +using Resolution = QString; +using Framerate = float; +using FrameratesList = QVector<Framerate>; +using ResRateList = QVector<QPair<Resolution, FrameratesList>>; +using Capabilities = QMap<Channel, ResRateList>; + +// This class is used to expose video data frame(currently only +// by the ShmRenderer class). +struct Frame +{ + // Used by SHM renderer. + uint8_t* ptr {nullptr}; + size_t size {0}; +}; + +enum class DeviceType { CAMERA, DISPLAY, FILE, INVALID }; +Q_ENUM_NS(DeviceType) + +// This class describes the current video input device. +struct RenderedDevice +{ + QString name; + DeviceType type = DeviceType::INVALID; +}; + +// This class describes current video settings +struct Settings +{ + Channel channel = ""; + QString name = ""; + QString id = ""; + Framerate rate = 0; + Resolution size = ""; +}; +} // namespace video +} // namespace api +} // namespace lrc diff --git a/src/libclient/authority/daemon.cpp b/src/libclient/authority/daemon.cpp new file mode 100644 index 0000000000000000000000000000000000000000..46f9b8bc5bee978b4b9c438b1d13c7895a3d3ce2 --- /dev/null +++ b/src/libclient/authority/daemon.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +// Lrc +#include "daemon.h" + +namespace lrc { + +namespace authority { + +namespace daemon { + +void +addContact(const api::account::Info& owner, const QString& contactUri) +{ + ConfigurationManager::instance().addContact(owner.id, contactUri); +} + +void +addContact(const api::account::Info& owner, const api::contact::Info& contactInfo) +{ + ConfigurationManager::instance().addContact(owner.id, contactInfo.profileInfo.uri); +} + +void +removeContact(const api::account::Info& owner, const QString& contactUri, bool banned) +{ + ConfigurationManager::instance().removeContact(owner.id, contactUri, banned); +} + +bool +addContactFromPending(const api::account::Info& owner, const QString& contactUri) +{ + return ConfigurationManager::instance().acceptTrustRequest(owner.id, contactUri); +} + +bool +discardFromPending(const api::account::Info& owner, const QString& contactUri) +{ + return ConfigurationManager::instance().discardTrustRequest(owner.id, contactUri); +} + +} // namespace daemon + +} // namespace authority + +} // namespace lrc diff --git a/src/libclient/authority/daemon.h b/src/libclient/authority/daemon.h new file mode 100644 index 0000000000000000000000000000000000000000..41f7f8532d35916e975812b7b40b791ad6bef0b9 --- /dev/null +++ b/src/libclient/authority/daemon.h @@ -0,0 +1,69 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +// Lrc +#include "api/account.h" +#include "api/contact.h" +#include "dbus/configurationmanager.h" + +namespace lrc { + +namespace authority { + +namespace daemon { +/** + * Ask the daemon to add contact to the daemon. + * @param owner + * @param contactUri + */ +void addContact(const api::account::Info& owner, const QString& contactUri); +/** + * Ask the daemon to add contact to the daemon. + * @param owner + * @param contactInfo + */ +void addContact(const api::account::Info& owner, const api::contact::Info& contactInfo); +/** + * Ask the daemon to remove a contact and may ban it. + * @param owner + * @param contactInfo + * @param banned + */ +void removeContact(const api::account::Info& owner, const QString& contactUri, bool banned); +/** + * Ask the daemon to add a contact from the pending list. + * @param owner + * @param contactUri + * @return if operation succeed + */ +bool addContactFromPending(const api::account::Info& owner, const QString& contactUri); +/** + * Ask the daemon to discard a pending. + * @param owner + * @param contactUri + * @return if operation succeed + */ +bool discardFromPending(const api::account::Info& owner, const QString& contactUri); + +} // namespace daemon + +} // namespace authority + +} // namespace lrc diff --git a/src/libclient/authority/storagehelper.cpp b/src/libclient/authority/storagehelper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..02979e09518b1a266eb1f9083caef08e1f80a9b2 --- /dev/null +++ b/src/libclient/authority/storagehelper.cpp @@ -0,0 +1,1381 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com> * + * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#include "storagehelper.h" + +#include "api/profile.h" +#include "api/conversation.h" +#include "api/datatransfer.h" +#include "api/lrc.h" +#include "uri.h" +#include "vcard.h" + +#include <account_const.h> +#include <datatransfer_interface.h> + +#include <QImage> +#include <QByteArray> +#include <QBuffer> +#include <QLockFile> +#include <QJsonObject> +#include <QJsonDocument> + +#include <fstream> +#include <thread> +#include <cstring> + +namespace lrc { + +namespace authority { + +namespace storage { + +QString +getPath() +{ +#ifdef Q_OS_WIN + auto definedDataDir = qEnvironmentVariable("JAMI_DATA_HOME"); + if (!definedDataDir.isEmpty()) + return QDir(definedDataDir).absolutePath() + "/"; +#endif + QDir dataDir(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)); + // Avoid to depends on the client name. + dataDir.cdUp(); + return dataDir.absolutePath() + "/jami/"; +} + +static QString +profileVcardPath(const QString& accountId, const QString& uri) +{ + auto accountLocalPath = getPath() + accountId + QDir::separator(); + if (uri.isEmpty()) + return accountLocalPath + "profile.vcf"; + + auto fileName = QString(uri.toUtf8().toBase64()); + return accountLocalPath + "profiles" + QDir::separator() + fileName + ".vcf"; +} + +static QString +stringFromJSON(const QJsonObject& json) +{ + QJsonDocument doc(json); + return QString::fromLocal8Bit(doc.toJson(QJsonDocument::Compact)); +} + +static QJsonObject +JSONFromString(const QString& str) +{ + QJsonObject json; + QJsonDocument doc = QJsonDocument::fromJson(str.toUtf8()); + + if (!doc.isNull()) { + if (doc.isObject()) { + json = doc.object(); + } else { + qDebug() << "Document is not a JSON object: " << str; + } + } else { + qDebug() << "Invalid JSON: " << str; + } + return json; +} + +static QString +JSONStringFromInitList(const std::initializer_list<QPair<QString, QJsonValue>> args) +{ + QJsonObject jsonObject(args); + return stringFromJSON(jsonObject); +} + +static QString +readJSONValue(const QJsonObject& json, const QString& key) +{ + if (!json.isEmpty() && json.contains(key) && json[key].isString()) { + if (json[key].isString()) { + return json[key].toString(); + } + } + return {}; +} + +static void +writeJSONValue(QJsonObject& json, const QString& key, const QString& value) +{ + json[key] = value; +} + +QString +prepareUri(const QString& uri, api::profile::Type type) +{ + URI uriObject(uri); + switch (type) { + case api::profile::Type::SIP: + return uriObject.format(URI::Section::USER_INFO | URI::Section::HOSTNAME); + break; + case api::profile::Type::JAMI: + return uriObject.format(URI::Section::USER_INFO); + break; + case api::profile::Type::INVALID: + case api::profile::Type::PENDING: + case api::profile::Type::TEMPORARY: + case api::profile::Type::COUNT__: + default: + return uri; + } +} + +QString +getFormattedCallDuration(const std::time_t duration) +{ + if (duration == 0) + return {}; + std::string formattedString; + auto minutes = duration / 60; + auto seconds = duration % 60; + if (minutes > 0) { + formattedString += std::to_string(minutes) + ":"; + if (formattedString.length() == 2) { + formattedString = "0" + formattedString; + } + } else { + formattedString += "00:"; + } + if (seconds < 10) + formattedString += "0"; + formattedString += std::to_string(seconds); + return QString::fromStdString(formattedString); +} + +QString +getCallInteractionString(const QString& authorUri, const std::time_t& duration) +{ + if (duration < 0) { + if (authorUri.isEmpty()) { + return QObject::tr("Outgoing call"); + } else { + return QObject::tr("Incoming call"); + } + } else if (authorUri.isEmpty()) { + if (duration) { + return QObject::tr("Outgoing call") + " - " + getFormattedCallDuration(duration); + } else { + return QObject::tr("Missed outgoing call"); + } + } else { + if (duration) { + return QObject::tr("Incoming call") + " - " + getFormattedCallDuration(duration); + } else { + return QObject::tr("Missed incoming call"); + } + } +} + +QString +getContactInteractionString(const QString& authorUri, const api::interaction::Status& status) +{ + if (authorUri.isEmpty()) { + return QObject::tr("Contact added"); + } else { + if (status == api::interaction::Status::UNKNOWN) { + return QObject::tr("Invitation received"); + } else if (status == api::interaction::Status::SUCCESS) { + return QObject::tr("Invitation accepted"); + } + } + return {}; +} + +namespace vcard { +QString compressedAvatar(const QString& image); + +QString +compressedAvatar(const QString& image) +{ + QImage qimage; + // Avoid to use all formats. Some seems bugguy, like libpbf, asking + // for a QGuiApplication for QFontDatabase + auto ret = qimage.loadFromData(QByteArray::fromBase64(image.toUtf8()), "JPEG"); + if (!ret) + ret = qimage.loadFromData(QByteArray::fromBase64(image.toUtf8()), "PNG"); + if (!ret) { + qDebug() << "vCard image loading failed"; + return ""; + } + QByteArray bArray; + QBuffer buffer(&bArray); + buffer.open(QIODevice::WriteOnly); + + auto size = qMin(qimage.width(), qimage.height()); + auto rect = QRect((qimage.width() - size) / 2, (qimage.height() - size) / 2, size, size); + constexpr auto quality = 88; // Same as android, between 80 and 90 jpeg compression changes a lot + constexpr auto maxSize = 16000 * 8; // Because 16*3 (rgb) = 48k, which is a valid size for the + // DHT and * 8 because typical jpeg compression + // divides the size per 8 + while (size * size > maxSize) + size /= 2; + qimage.copy(rect).scaled({size, size}, Qt::KeepAspectRatio).save(&buffer, "JPEG", quality); + auto b64Img = bArray.toBase64().trimmed(); + return QString::fromLocal8Bit(b64Img.constData(), b64Img.length()); +} + +QString +profileToVcard(const api::profile::Info& profileInfo, bool compressImage) +{ + using namespace api; + bool compressedImage = std::strncmp(profileInfo.avatar.toStdString().c_str(), "/9j/", 4) == 0; + if (compressedImage && !compressImage) { + compressImage = false; + } + QString vCardStr = vCard::Delimiter::BEGIN_TOKEN; + vCardStr += vCard::Delimiter::END_LINE_TOKEN; + vCardStr += vCard::Property::VERSION; + vCardStr += ":2.1"; + vCardStr += vCard::Delimiter::END_LINE_TOKEN; + vCardStr += vCard::Property::FORMATTED_NAME; + vCardStr += ":"; + vCardStr += profileInfo.alias; + vCardStr += vCard::Delimiter::END_LINE_TOKEN; + if (profileInfo.type == profile::Type::JAMI) { + vCardStr += vCard::Property::TELEPHONE; + vCardStr += vCard::Delimiter::SEPARATOR_TOKEN; + vCardStr += "other:ring:"; + vCardStr += profileInfo.uri; + vCardStr += vCard::Delimiter::END_LINE_TOKEN; + } else { + vCardStr += vCard::Property::TELEPHONE; + vCardStr += ":"; + vCardStr += profileInfo.uri; + vCardStr += vCard::Delimiter::END_LINE_TOKEN; + } + vCardStr += vCard::Property::PHOTO; + vCardStr += vCard::Delimiter::SEPARATOR_TOKEN; + vCardStr += vCard::Property::BASE64; + vCardStr += vCard::Delimiter::SEPARATOR_TOKEN; + if (compressImage) { + vCardStr += vCard::Property::TYPE_JPEG; + vCardStr += ":"; + vCardStr += compressedImage ? profileInfo.avatar : compressedAvatar(profileInfo.avatar); + } else { + vCardStr += compressedImage ? vCard::Property::TYPE_JPEG : vCard::Property::TYPE_PNG; + vCardStr += ":"; + vCardStr += profileInfo.avatar; + } + vCardStr += vCard::Delimiter::END_LINE_TOKEN; + vCardStr += vCard::Delimiter::END_TOKEN; + return vCardStr; +} + +void +setProfile(const QString& accountId, const api::profile::Info& profileInfo, const bool isPeer) +{ + auto vcard = vcard::profileToVcard(profileInfo); + auto path = profileVcardPath(accountId, isPeer ? profileInfo.uri : ""); + QLockFile lf(path + ".lock"); + QFile file(path); + if (!lf.lock()) { + qWarning().noquote() << "Can't lock file for writing: " << file.fileName(); + return; + } + if (!file.open(QIODevice::WriteOnly)) { + lf.unlock(); + qWarning().noquote() << "Can't open file for writing: " << file.fileName(); + return; + } + QTextStream(&file) << vcard; + file.close(); + lf.unlock(); +} +} // namespace vcard + +VectorString +getConversationsWithPeer(Database& db, const QString& participant_uri) +{ + return db + .select("id", + "conversations", + "participant=:participant", + {{":participant", participant_uri}}) + .payloads; +} + +VectorString +getPeerParticipantsForConversation(Database& db, const QString& conversationId) +{ + return db.select("participant", "conversations", "id=:id", {{":id", conversationId}}).payloads; +} + +void +createOrUpdateProfile(const QString& accountId, + const api::profile::Info& profileInfo, + const bool isPeer) +{ + if (isPeer) { + auto contact = storage::buildContactFromProfile(accountId, + profileInfo.uri, + profileInfo.type); + if (!profileInfo.alias.isEmpty()) + contact.profileInfo.alias = profileInfo.alias; + if (!profileInfo.avatar.isEmpty()) + contact.profileInfo.avatar = profileInfo.avatar; + vcard::setProfile(accountId, contact.profileInfo, isPeer); + return; + } + vcard::setProfile(accountId, profileInfo, isPeer); +} + +void +removeProfile(const QString& accountId, const QString& peerUri) +{ + auto path = profileVcardPath(accountId, peerUri); + if (!QFile::remove(path)) { + qWarning() << "Couldn't remove vcard for" << peerUri << "at" << path; + } +} + +QString +getAccountAvatar(const QString& accountId) +{ + auto accountLocalPath = getPath() + accountId + "/"; + QString filePath; + filePath = accountLocalPath + "profile.vcf"; + QFile file(filePath); + if (!file.open(QIODevice::ReadOnly)) + return {}; + const auto vCard = lrc::vCard::utils::toHashMap(file.readAll()); + const auto photo = (vCard.find(vCard::Property::PHOTO_PNG) == vCard.end()) + ? vCard[vCard::Property::PHOTO_JPEG] + : vCard[vCard::Property::PHOTO_PNG]; + return photo; +} + +api::contact::Info +buildContactFromProfile(const QString& accountId, + const QString& peer_uri, + const api::profile::Type& type) +{ + lrc::api::profile::Info profileInfo; + profileInfo.uri = peer_uri; + profileInfo.type = type; + auto accountLocalPath = getPath() + accountId + "/"; + QString b64filePath; + b64filePath = profileVcardPath(accountId, peer_uri); + QFile file(b64filePath); + if (!file.open(QIODevice::ReadOnly)) { + // try non-base64 path + QString filePath = accountLocalPath + "profiles/" + peer_uri + ".vcf"; + file.setFileName(filePath); + if (!file.open(QIODevice::ReadOnly)) { + return {profileInfo, "", true, false}; + } + // rename it + qWarning().noquote() << "Renaming profile: " << filePath; + file.rename(b64filePath); + // reopen it + if (!file.open(QIODevice::ReadOnly)) { + qWarning().noquote() << "Can't open file: " << b64filePath; + return {profileInfo, "", true, false}; + } + } + const auto vCard = lrc::vCard::utils::toHashMap(file.readAll()); + const auto alias = vCard[vCard::Property::FORMATTED_NAME]; + if (lrc::api::Lrc::cacheAvatars.load()) { + for (const auto& key : vCard.keys()) { + if (key.contains("PHOTO")) + profileInfo.avatar = vCard[key]; + } + } + profileInfo.alias = alias; + return {profileInfo, "", type == api::profile::Type::JAMI, false}; +} + +QString +avatar(const QString& accountId, const QString& contactId) +{ + if (contactId.isEmpty()) + return getAccountAvatar(accountId); + auto accountLocalPath = getPath() + accountId + "/"; + QString b64filePath; + b64filePath = profileVcardPath(accountId, contactId); + QFile file(b64filePath); + if (!file.open(QIODevice::ReadOnly)) { + return {}; + } + const auto vCard = lrc::vCard::utils::toHashMap(file.readAll()); + for (const auto& key : vCard.keys()) { + if (key.contains("PHOTO")) + return vCard[key]; + } + return {}; +} + +VectorString +getAllConversations(Database& db) +{ + return db.select("id", "conversations", {}, {}).payloads; +} + +VectorString +getConversationsBetween(Database& db, const QString& peer1_uri, const QString& peer2_uri) +{ + auto conversationsForPeer1 = getConversationsWithPeer(db, peer1_uri); + std::sort(conversationsForPeer1.begin(), conversationsForPeer1.end()); + auto conversationsForPeer2 = getConversationsWithPeer(db, peer2_uri); + std::sort(conversationsForPeer2.begin(), conversationsForPeer2.end()); + VectorString common; + + std::set_intersection(conversationsForPeer1.begin(), + conversationsForPeer1.end(), + conversationsForPeer2.begin(), + conversationsForPeer2.end(), + std::back_inserter(common)); + return common; +} + +QString +beginConversationWithPeer(Database& db, + const QString& peer_uri, + const bool isOutgoing, + time_t timestamp) +{ + // Add conversation between account and profile + auto newConversationsId = db.select("IFNULL(MAX(id), 0) + 1", "conversations", "1=1", {}) + .payloads[0]; + db.insertInto("conversations", + {{":id", "id"}, {":participant", "participant"}}, + {{":id", newConversationsId}, {":participant", peer_uri}}); + api::interaction::Info msg {isOutgoing ? "" : peer_uri, + {}, + timestamp ? timestamp : std::time(nullptr), + 0, + api::interaction::Type::CONTACT, + isOutgoing ? api::interaction::Status::SUCCESS + : api::interaction::Status::UNKNOWN, + isOutgoing}; + // Add first interaction + addMessageToConversation(db, newConversationsId, msg); + return newConversationsId; +} + +void +getHistory(Database& db, api::conversation::Info& conversation) +{ + auto interactionsResult + = db.select("id, author, body, timestamp, type, status, is_read, extra_data", + "interactions", + "conversation=:conversation", + {{":conversation", conversation.uid}}); + auto nCols = 8; + if (interactionsResult.nbrOfCols == nCols) { + auto payloads = interactionsResult.payloads; + for (decltype(payloads.size()) i = 0; i < payloads.size(); i += nCols) { + QString durationString; + auto extra_data_str = payloads[i + 7]; + if (!extra_data_str.isEmpty()) { + auto jsonData = JSONFromString(extra_data_str); + durationString = readJSONValue(jsonData, "duration"); + } + auto body = payloads[i + 2]; + auto type = api::interaction::to_type(payloads[i + 4]); + std::time_t duration = durationString.isEmpty() + ? 0 + : std::stoi(durationString.toStdString()); + auto status = api::interaction::to_status(payloads[i + 5]); + if (type == api::interaction::Type::CALL) { + body = getCallInteractionString(payloads[i + 1], duration); + } else if (type == api::interaction::Type::CONTACT) { + body = getContactInteractionString(payloads[i + 1], status); + } + auto msg = api::interaction::Info({payloads[i + 1], + body, + std::stoi(payloads[i + 3].toStdString()), + duration, + type, + status, + (payloads[i + 6] == "1" ? true : false)}); + conversation.interactions->emplace(payloads[i], std::move(msg)); + conversation.lastMessageUid = payloads[i]; + if (status != api::interaction::Status::DISPLAYED || !payloads[i + 1].isEmpty()) { + continue; + } + conversation.interactions->setRead(conversation.participants.front().uri, payloads[i]); + } + } +} + +QString +addMessageToConversation(Database& db, + const QString& conversationId, + const api::interaction::Info& msg) +{ + return db.insertInto("interactions", + {{":author", "author"}, + {":conversation", "conversation"}, + {":timestamp", "timestamp"}, + {":body", "body"}, + {":type", "type"}, + {":status", "status"}, + {":is_read", "is_read"}}, + {{":author", msg.authorUri}, + {":conversation", conversationId}, + {":timestamp", toQString(msg.timestamp)}, + {":body", msg.body}, + {":type", to_string(msg.type)}, + {":status", to_string(msg.status)}, + {":is_read", msg.isRead ? "1" : "0"}}); +} + +QString +addOrUpdateMessage(Database& db, + const QString& conversationId, + const api::interaction::Info& msg, + const QString& daemonId) +{ + // Check if profile is already present. + auto msgAlreadyExists = db.select("id", + "interactions", + "author=:author AND daemon_id=:daemon_id", + {{":author", msg.authorUri}, {":daemon_id", daemonId}}) + .payloads; + if (msgAlreadyExists.empty()) { + auto extra_data_JSON = JSONFromString(""); + writeJSONValue(extra_data_JSON, "duration", QString::number(msg.duration)); + auto extra_data = stringFromJSON(extra_data_JSON); + return db.insertInto("interactions", + {{":author", "author"}, + {":conversation", "conversation"}, + {":timestamp", "timestamp"}, + {":body", "body"}, + {":type", "type"}, + {":status", "status"}, + {":daemon_id", "daemon_id"}, + {":extra_data", "extra_data"}}, + {{":author", msg.authorUri.isEmpty() ? "" : msg.authorUri}, + {":conversation", conversationId}, + {":timestamp", toQString(msg.timestamp)}, + {msg.body.isEmpty() ? "" : ":body", msg.body}, + {":type", to_string(msg.type)}, + {daemonId.isEmpty() ? "" : ":daemon_id", daemonId}, + {":status", to_string(msg.status)}, + {extra_data.isEmpty() ? "" : ":extra_data", extra_data}}); + } else { + // already exists @ id(msgAlreadyExists[0]) + auto id = msgAlreadyExists[0]; + QString extra_data; + if (msg.type == api::interaction::Type::CALL) { + auto duration = std::max(msg.duration, static_cast<std::time_t>(0)); + auto extra_data_str = getInteractionExtraDataById(db, id); + auto extra_data_JSON = JSONFromString(extra_data_str); + writeJSONValue(extra_data_JSON, "duration", QString::number(duration)); + extra_data = stringFromJSON(extra_data_JSON); + } + db.update("interactions", + {"body=:body, extra_data=:extra_data"}, + {{msg.body.isEmpty() ? "" : ":body", msg.body}, + {extra_data.isEmpty() ? "" : ":extra_data", extra_data}}, + "id=:id", + {{":id", id}}); + return id; + } +} + +QString +addDataTransferToConversation(Database& db, + const QString& conversationId, + const api::datatransfer::Info& infoFromDaemon) +{ + auto convId = conversationId.isEmpty() ? NULL : conversationId; + return db.insertInto("interactions", + {{":author", "author"}, + {":conversation", "conversation"}, + {":timestamp", "timestamp"}, + {":body", "body"}, + {":type", "type"}, + {":status", "status"}, + {":is_read", "is_read"}, + {":daemon_id", "daemon_id"}}, + {{":author", infoFromDaemon.isOutgoing ? "" : infoFromDaemon.peerUri}, + {":conversation", convId}, + {":timestamp", toQString(std::time(nullptr))}, + {":body", infoFromDaemon.path}, + {":type", "DATA_TRANSFER"}, + {":status", "TRANSFER_CREATED"}, + {":is_read", "0"}, + {":daemon_id", infoFromDaemon.uid}}); +} + +void +addDaemonMsgId(Database& db, const QString& interactionId, const QString& daemonId) +{ + db.update("interactions", + "daemon_id=:daemon_id", + {{":daemon_id", daemonId}}, + "id=:id", + {{":id", interactionId}}); +} + +QString +getDaemonIdByInteractionId(Database& db, const QString& id) +{ + auto ids = db.select("daemon_id", "interactions", "id=:id", {{":id", id}}).payloads; + return ids.empty() ? "" : ids[0]; +} + +QString +getInteractionIdByDaemonId(Database& db, const QString& daemon_id) +{ + auto ids = db.select("id", "interactions", "daemon_id=:daemon_id", {{":daemon_id", daemon_id}}) + .payloads; + return ids.empty() ? "" : ids[0]; +} + +void +updateDataTransferInteractionForDaemonId(Database& db, + const QString& daemonId, + api::interaction::Info& interaction) +{ + auto result = db.select("body, status", + "interactions", + "daemon_id=:daemon_id", + {{":daemon_id", daemonId}}) + .payloads; + if (result.size() < 2) { + return; + } + auto body = result[0]; + auto status = api::interaction::to_status(result[1]); + interaction.body = body; + interaction.status = status; +} + +QString +getInteractionExtraDataById(Database& db, const QString& id, const QString& key) +{ + auto extra_datas = db.select("extra_data", "interactions", "id=:id", {{":id", id}}).payloads; + if (key.isEmpty()) { + return extra_datas.empty() ? "" : extra_datas[0]; + } + QString value; + if (!extra_datas[0].isEmpty()) { + value = readJSONValue(JSONFromString(extra_datas[0]), key); + } + return value; +} + +void +updateInteractionBody(Database& db, const QString& id, const QString& newBody) +{ + db.update("interactions", "body=:body", {{":body", newBody}}, "id=:id", {{":id", id}}); +} + +void +updateInteractionStatus(Database& db, const QString& id, api::interaction::Status newStatus) +{ + db.update("interactions", + {"status=:status"}, + {{":status", api::interaction::to_string(newStatus)}}, + "id=:id", + {{":id", id}}); +} + +void +setInteractionRead(Database& db, const QString& id) +{ + db.update("interactions", {"is_read=:is_read"}, {{":is_read", "1"}}, "id=:id", {{":id", id}}); +} + +QString +conversationIdFromInteractionId(Database& db, const QString& interactionId) +{ + auto result = db.select("conversation", "interactions", "id=:id", {{":id", interactionId}}); + if (result.nbrOfCols == 1 && result.payloads.size()) { + return result.payloads[0]; + } + return {}; +} + +void +clearHistory(Database& db, const QString& conversationId) +{ + try { + db.deleteFrom("interactions", + "conversation=:conversation", + {{":conversation", conversationId}}); + } catch (Database::QueryDeleteError& e) { + qWarning() << "deleteFrom error: " << e.details(); + } +} + +void +clearInteractionFromConversation(Database& db, + const QString& conversationId, + const QString& interactionId) +{ + try { + db.deleteFrom("interactions", + "conversation=:conversation AND id=:id", + {{":conversation", conversationId}, {":id", interactionId}}); + } catch (Database::QueryDeleteError& e) { + qWarning() << "deleteFrom error: " << e.details(); + } +} + +void +clearAllHistory(Database& db) +{ + try { + db.deleteFrom("interactions", "1=1", {}); + } catch (Database::QueryDeleteError& e) { + qWarning() << "deleteFrom error: " << e.details(); + } +} + +void +deleteObsoleteHistory(Database& db, long int date) +{ + try { + db.deleteFrom("interactions", "timestamp<=:date", {{":date", QString::number(date)}}); + } catch (Database::QueryDeleteError& e) { + qWarning() << "deleteFrom error: " << e.details(); + } +} + +void +removeContactConversations(Database& db, const QString& contactUri) +{ + // Get common conversations + auto conversations = getConversationsWithPeer(db, contactUri); + // Remove conversations + interactions + try { + for (const auto& conversationId : conversations) { + // Remove conversation + db.deleteFrom("conversations", "id=:id", {{":id", conversationId}}); + // clear History + db.deleteFrom("interactions", "conversation=:id", {{":id", conversationId}}); + } + } catch (Database::QueryDeleteError& e) { + qWarning() << "deleteFrom error: " << e.details(); + } +} + +int +countUnreadFromInteractions(Database& db, const QString& conversationId) +{ + return db.count("is_read", + "interactions", + "is_read=:is_read AND conversation=:id", + {{":is_read", "0"}, {":id", conversationId}}); +} + +uint64_t +getLastTimestamp(Database& db) +{ + auto timestamps = db.select("MAX(timestamp)", "interactions", "1=1", {}).payloads; + auto result = std::time(nullptr); + try { + if (!timestamps.empty() && !timestamps[0].isEmpty()) { + result = std::stoull(timestamps[0].toStdString()); + } + } catch (const std::out_of_range& e) { + qDebug() << "storage::getLastTimestamp, stoull throws an out_of_range exception: " + << e.what(); + } catch (const std::invalid_argument& e) { + qDebug() << "storage::getLastTimestamp, stoull throws an invalid_argument exception: " + << e.what(); + } + return result; +} + +//================================================================================ +// This section provides migration helpers from ring.db +// to per-account databases yielding a file structure like: +// +// { local_storage } / jami +// └──{ account_id } +// ├── config.yml +// ├── contacts +// ├── export.gz +// ├── incomingTrustRequests +// ├── knownDevicesNames +// ├── history.db < --conversations and interactions database +// ├── profile.vcf < --account vcard +// ├── profiles < --account contact vcards +// │ │──{ contact_uri }.vcf +// │ └── ... +// ├── ring_device.crt +// └── ring_device.key +//================================================================================ +namespace migration { + +enum class msgFlag { + IS_INCOMING, + IS_OUTGOING, + IS_CONTACT_ADDED, + IS_INVITATION_RECEIVED, + IS_INVITATION_ACCEPTED, + IS_TEXT +}; + +QString profileToVcard(const lrc::api::profile::Info&, const QString&); +uint64_t getTimeFromTimeStr(const QString&) noexcept; +std::pair<msgFlag, uint64_t> migrateMessageBody(const QString&, const lrc::api::interaction::Type&); +VectorString getPeerParticipantsForConversationId(lrc::Database&, const QString&, const QString&); +void migrateAccountDb(const QString&, + std::shared_ptr<lrc::Database>, + std::shared_ptr<lrc::Database>); + +namespace interaction { + +static inline api::interaction::Type +to_type(const QString& type) +{ + if (type == "TEXT") + return api::interaction::Type::TEXT; + else if (type == "CALL") + return api::interaction::Type::CALL; + else if (type == "CONTACT") + return api::interaction::Type::CONTACT; + else if (type == "OUTGOING_DATA_TRANSFER") + return api::interaction::Type::DATA_TRANSFER; + else if (type == "INCOMING_DATA_TRANSFER") + return api::interaction::Type::DATA_TRANSFER; + else + return api::interaction::Type::INVALID; +} + +static inline QString +to_migrated_status_string(const QString& status) +{ + if (status == "FAILED") + return "FAILURE"; + else if (status == "SUCCEED") + return "SUCCESS"; + else if (status == "READ") + return "SUCCESS"; + else if (status == "UNREAD") + return "SUCCESS"; + else + return status; +} + +} // namespace interaction + +QString +profileToVcard(const api::profile::Info& profileInfo, const QString& accountId = {}) +{ + using namespace api; + bool compressedImage = std::strncmp(profileInfo.avatar.toStdString().c_str(), "/9g=", 4) == 0; + ; + QString vCardStr = vCard::Delimiter::BEGIN_TOKEN; + vCardStr += vCard::Delimiter::END_LINE_TOKEN; + vCardStr += vCard::Property::VERSION; + vCardStr += ":2.1"; + vCardStr += vCard::Delimiter::END_LINE_TOKEN; + if (!accountId.isEmpty()) { + vCardStr += vCard::Property::UID; + vCardStr += ":"; + vCardStr += accountId; + vCardStr += vCard::Delimiter::END_LINE_TOKEN; + } + vCardStr += vCard::Property::FORMATTED_NAME; + vCardStr += ":"; + vCardStr += profileInfo.alias; + vCardStr += vCard::Delimiter::END_LINE_TOKEN; + if (profileInfo.type == profile::Type::JAMI) { + vCardStr += vCard::Property::TELEPHONE; + vCardStr += ":"; + vCardStr += vCard::Delimiter::SEPARATOR_TOKEN; + vCardStr += "other:ring:"; + vCardStr += profileInfo.uri; + vCardStr += vCard::Delimiter::END_LINE_TOKEN; + } else { + vCardStr += vCard::Property::TELEPHONE; + vCardStr += profileInfo.uri; + vCardStr += vCard::Delimiter::END_LINE_TOKEN; + } + vCardStr += vCard::Property::PHOTO; + vCardStr += vCard::Delimiter::SEPARATOR_TOKEN; + vCardStr += "ENCODING=BASE64"; + vCardStr += vCard::Delimiter::SEPARATOR_TOKEN; + vCardStr += compressedImage ? "TYPE=JPEG:" : "TYPE=PNG:"; + vCardStr += profileInfo.avatar; + vCardStr += vCard::Delimiter::END_LINE_TOKEN; + vCardStr += vCard::Delimiter::END_TOKEN; + return vCardStr; +} + +uint64_t +getTimeFromTimeStr(const QString& str) noexcept +{ + uint64_t minutes = 0, seconds = 0; + std::string timeStr = str.toStdString(); + std::size_t delimiterPos = timeStr.find(":"); + if (delimiterPos != std::string::npos) { + try { + minutes = std::stoull(timeStr.substr(0, delimiterPos)); + seconds = std::stoull(timeStr.substr(delimiterPos + 1)); + } catch (const std::exception&) { + return 0; + } + } + return minutes * 60 + seconds; +} + +std::pair<msgFlag, uint64_t> +migrateMessageBody(const QString& body, const api::interaction::Type& type) +{ + uint64_t duration {0}; + // check in english and local to determine the direction of the call + static QString emo = "Missed outgoing call"; + static QString lmo = QObject::tr("Missed outgoing call"); + static QString eo = "Outgoing call"; + static QString lo = QObject::tr("Outgoing call"); + static QString eca = "Contact added"; + static QString lca = QObject::tr("Contact added"); + static QString eir = "Invitation received"; + static QString lir = QObject::tr("Invitation received"); + static QString eia = "Invitation accepted"; + static QString lia = QObject::tr("Invitation accepted"); + auto strBody = body.toStdString(); + switch (type) { + case api::interaction::Type::CALL: { + bool en_missedOut = body.contains(emo); + bool en_out = body.contains(eo); + bool loc_missedOut = body.contains(lmo); + bool loc_out = body.contains(lo); + bool outgoingCall = en_missedOut || en_out || loc_missedOut || loc_out; + std::size_t dashPos = strBody.find("-"); + if (dashPos != std::string::npos) { + duration = getTimeFromTimeStr(toQString(strBody.substr(dashPos + 2))); + } + return std::make_pair(msgFlag(outgoingCall), duration); + } break; + case api::interaction::Type::CONTACT: + if (body.contains(eca) || body.contains(lca)) { + return std::make_pair(msgFlag::IS_CONTACT_ADDED, 0); + } else if (body.contains(eir) || body.contains(lir)) { + return std::make_pair(msgFlag::IS_INVITATION_RECEIVED, 0); + } else if (body.contains(eia) || body.contains(lia)) { + return std::make_pair(msgFlag::IS_INVITATION_ACCEPTED, 0); + } + break; + case api::interaction::Type::INVALID: + case api::interaction::Type::TEXT: + case api::interaction::Type::DATA_TRANSFER: + case api::interaction::Type::COUNT__: + default: + return std::make_pair(msgFlag::IS_TEXT, 0); + } + return std::make_pair(msgFlag::IS_OUTGOING, 0); +} + +VectorString +getPeerParticipantsForConversationId(Database& db, + const QString& profileId, + const QString& conversationId) +{ + return db + .select("participant_id", + "conversations", + "id=:id AND participant_id!=:participant_id", + {{":id", conversationId}, {":participant_id", profileId}}) + .payloads; +} + +void +migrateAccountDb(const QString& accountId, + std::shared_ptr<Database> db, + std::shared_ptr<Database> legacyDb) +{ + using namespace lrc::api; + using namespace migration; + + auto accountLocalPath = getPath() + accountId + "/"; + + using namespace DRing::Account; + MapStringString accountDetails = ConfigurationManager::instance().getAccountDetails( + accountId.toStdString().c_str()); + bool isRingAccount = accountDetails[ConfProperties::TYPE] == "RING"; + std::map<QString, QString> profileIdUriMap; + std::map<QString, QString> convIdPeerUriMap; + QString accountProfileId; + + // 1. profiles_accounts + // migrate account's avatar/alias from profiles table to {data_dir}/profile.vcf + QString accountUri; + if (isRingAccount) { + accountUri = accountDetails[DRing::Account::ConfProperties::USERNAME].contains("ring:") + ? QString(accountDetails[DRing::Account::ConfProperties::USERNAME]) + .remove(QString("ring:")) + : accountDetails[DRing::Account::ConfProperties::USERNAME]; + } else { + accountUri = accountDetails[DRing::Account::ConfProperties::USERNAME]; + } + + auto accountProfileIds = legacyDb + ->select("profile_id", + "profiles_accounts", + "account_id=:account_id AND is_account=:is_account", + {{":account_id", accountId}, {":is_account", "true"}}) + .payloads; + if (accountProfileIds.size() != 1) { + return; + } + accountProfileId = accountProfileIds[0]; + auto accountProfile + = legacyDb->select("photo, alias", "profiles", "id=:id", {{":id", accountProfileId}}) + .payloads; + profile::Info accountProfileInfo; + // if we can not find the uri in the database + // (in the case of poorly kept SIP account uris), + // than we cannot migrate the conversations and vcard + if (!accountProfile.empty()) { + accountProfileInfo = {accountUri, + accountProfile[0], + accountProfile[1], + isRingAccount ? profile::Type::JAMI : profile::Type::SIP}; + } + auto accountVcard = profileToVcard(accountProfileInfo, accountId); + QDir dir; + if (!dir.exists(accountLocalPath)) { + dir.mkpath(accountLocalPath); + } + auto profileFilePath = accountLocalPath + "profile.vcf"; + QFile file(profileFilePath); + if (!file.open(QIODevice::WriteOnly)) { + throw std::runtime_error("Can't open file: " + profileFilePath.toStdString()); + } + QTextStream(&file) << accountVcard; + + // 2. profiles + // migrate profiles from profiles table to {data_dir}/{uri}.vcf + // - for JAMI, the scheme and the hostname is omitted + // - for SIP, the uri is must be stripped of prefix and port + // e.g. 3d1112ab2bb089370c0744a44bbbb0786418d40b.vcf + // username.vcf or username@hostname.vcf + + // only select non-account profiles + auto profileIds = legacyDb + ->select("profile_id", + "profiles_accounts", + "account_id=:account_id AND is_account=:is_account", + {{":account_id", accountId}, {":is_account", "false"}}) + .payloads; + for (const auto& profileId : profileIds) { + auto profile = legacyDb + ->select("uri, alias, photo, type", + "profiles", + "id=:id", + {{":id", profileId}}) + .payloads; + if (profile.empty()) { + continue; + } + profile::Info profileInfo {profile[0], profile[2], profile[1]}; + auto uri = URI(profile[0]); + auto profileUri = uri.userinfo(); + if (!isRingAccount && uri.hasHostname()) { + profileUri += "@" + uri.hostname(); + } + // insert into map for use during the conversations table migration + profileIdUriMap.insert(std::make_pair(profileId, profileUri)); + auto vcard = profileToVcard(profileInfo); + // make sure the directory exists + QDir dir(accountLocalPath + "profiles"); + if (!dir.exists()) + dir.mkpath("."); + profileFilePath = accountLocalPath + "profiles/" + profileUri + ".vcf"; + QFile file(profileFilePath); + // if we catch duplicates here, skip the profile because + // the previous db structure does not guarantee unique uris + if (file.exists()) { + qWarning() << "Profile file already exits: " << profileFilePath; + continue; + } + if (!file.open(QIODevice::WriteOnly)) { + qWarning() << "Can't open file: " << profileFilePath; + continue; + } + QTextStream(&file) << vcard; + } + + // 3. conversations + // migrate old conversations table ==> new conversations table + // a) participant_id INTEGER becomes participant TEXT (the uri of the participant) + // use the selected non-account profiles + auto conversationIds = legacyDb + ->select("id", + "conversations", + "participant_id=:participant_id", + {{":participant_id", accountProfileId}}) + .payloads; + if (conversationIds.empty()) { + return; + } + for (auto conversationId : conversationIds) { + // only one peer pre-groupchat + auto peerProfileId = getPeerParticipantsForConversationId(*legacyDb, + accountProfileId, + conversationId); + if (peerProfileId.empty()) { + continue; + } + auto it = profileIdUriMap.find(peerProfileId.at(0)); + // we cannot insert in the conversations table without a uri + if (it == profileIdUriMap.end()) { + continue; + } + convIdPeerUriMap.insert(std::make_pair(conversationId, it->second)); + try { + db->insertInto("conversations", + {{":id", "id"}, {":participant", "participant"}}, + {{":id", conversationId}, {":participant", it->second}}); + } catch (const std::runtime_error& e) { + qWarning() << "Couldn't migrate conversation: " << e.what(); + continue; + } + } + + // 4. interactions + auto allInteractions = legacyDb->select("account_id, author_id, conversation_id, \ + timestamp, body, type, status, daemon_id", + "interactions", + "account_id=:account_id", + {{":account_id", accountProfileId}}); + auto interactionIt = allInteractions.payloads.begin(); + while (interactionIt != allInteractions.payloads.end()) { + auto author_id = *(interactionIt + 1); + auto convId = *(interactionIt + 2); + auto timestamp = *(interactionIt + 3); + auto body = *(interactionIt + 4); + auto type = interaction::to_type(*(interactionIt + 5)); + auto statusStr = *(interactionIt + 6); + auto daemonId = *(interactionIt + 7); + + auto it = profileIdUriMap.find(author_id); + if (it == profileIdUriMap.end() && author_id != accountProfileId) { + std::advance(interactionIt, allInteractions.nbrOfCols); + continue; + } + // migrate body+type ==> msgFlag+duration + auto migratedMsg = migrateMessageBody(body, type); + QString profileUri = it == profileIdUriMap.end() ? "" : it->second; + // clear author uri if outgoing + switch (migratedMsg.first) { + case msgFlag::IS_OUTGOING: + case msgFlag::IS_CONTACT_ADDED: + profileUri.clear(); + break; + case msgFlag::IS_INCOMING: + case msgFlag::IS_INVITATION_RECEIVED: + case msgFlag::IS_INVITATION_ACCEPTED: { + // try to set profile uri using the conversation id + auto it = convIdPeerUriMap.find(convId); + if (it == convIdPeerUriMap.end()) { + std::advance(interactionIt, allInteractions.nbrOfCols); + continue; + } + profileUri = it->second; + break; + } + case msgFlag::IS_TEXT: + default: + break; + } + // Set all read, call and datatransfer, and contact added + // interactions to a read state + bool is_read = statusStr != "UNREAD" || type == api::interaction::Type::CALL + || type == api::interaction::Type::CONTACT; + // migrate status + if (migratedMsg.first == msgFlag::IS_INVITATION_RECEIVED) { + statusStr = "UNKNOWN"; + } + QString extra_data = migratedMsg.second == 0 + ? "" + : JSONStringFromInitList( + {qMakePair(QString("duration"), + QJsonValue(QString::number(migratedMsg.second)))}); + if (accountUri == profileUri) + profileUri.clear(); + auto typeStr = api::interaction::to_string(type); + try { + db->insertInto("interactions", + {{":author", "author"}, + {":conversation", "conversation"}, + {":timestamp", "timestamp"}, + {":body", "body"}, + {":type", "type"}, + {":status", "status"}, + {":is_read", "is_read"}, + {":daemon_id", "daemon_id"}, + {":extra_data", "extra_data"}}, + {{":author", profileUri}, + {":conversation", convId}, + {":timestamp", timestamp}, + {migratedMsg.first != msgFlag::IS_TEXT ? "" : ":body", body}, + {":type", api::interaction::to_string(type)}, + {":status", interaction::to_migrated_status_string(statusStr)}, + {":is_read", is_read ? "1" : "0"}, + {daemonId.isEmpty() ? "" : ":daemon_id", daemonId}, + {extra_data.isEmpty() ? "" : ":extra_data", extra_data}}); + } catch (const std::runtime_error& e) { + qWarning() << e.what(); + } + std::advance(interactionIt, allInteractions.nbrOfCols); + } + qDebug() << "Done"; +} + +} // namespace migration + +std::vector<std::shared_ptr<Database>> +migrateIfNeeded(const QStringList& accountIds, MigrationCb& willMigrateCb, MigrationCb& didMigrateCb) +{ + using namespace lrc::api; + using namespace migration; + + std::vector<std::shared_ptr<Database>> dbs(accountIds.size()); + + if (!accountIds.size()) { + qDebug() << "No accounts to migrate"; + return dbs; + } + + auto appPath = getPath(); + + // ring -> jami path migration + QDir dataDir(appPath); + // create data directory if not created yet + dataDir.mkpath(appPath); + QDir oldDataDir(appPath); + oldDataDir.cdUp(); + oldDataDir = oldDataDir.absolutePath() +#if defined(_WIN32) + + "/Savoir-faire Linux/Ring"; +#elif defined(__APPLE__) + + "/ring"; +#else + + "/gnome-ring"; +#endif + QStringList filesList = oldDataDir.entryList(); + QString filename; + QDir dir; + bool success = true; + Q_FOREACH (filename, filesList) { + qDebug() << "Migrate " << oldDataDir.absolutePath() << "/" << filename << " to " + << dataDir.absolutePath() + "/" + filename; + if (filename != "." && filename != "..") { + success &= dir.rename(oldDataDir.absolutePath() + "/" + filename, + dataDir.absolutePath() + "/" + filename); + } + } + if (success) { + // Remove old directory if the migration is successful. +#if defined(_WIN32) + oldDataDir.cdUp(); +#endif + oldDataDir.removeRecursively(); + } + + bool needsMigration = false; + std::map<QString, bool> hasMigratedData; + for (const auto& accountId : accountIds) { + auto hasMigratedDb = QFile(appPath + accountId + "/history.db").exists() + && !QFile(appPath + accountId + "/history.db-journal").exists(); + hasMigratedData.insert(std::make_pair(accountId, hasMigratedDb)); + needsMigration |= !hasMigratedDb; + } + if (!needsMigration) { + // if there's any lingering pre-migration data, remove it + QFile(dataDir.absoluteFilePath("ring.db")).remove(); + QDir(dataDir.absoluteFilePath("text/")).removeRecursively(); + QDir(dataDir.absoluteFilePath("profiles/")).removeRecursively(); + QDir(dataDir.absoluteFilePath("peer_profiles/")).removeRecursively(); + qDebug() << "No migration required"; + return dbs; + } + + // A fairly long migration may now occur + std::thread migrateThread( + [&appPath, &accountIds, &dbs, &didMigrateCb, &dataDir, &hasMigratedData] { + // 1. migrate old lrc -> new lrc if needed + // 2. migrate new lrc db version 1 -> db version 1.1 if needed + // the destructor of LegacyDatabase will remove 'ring.db' and clean out + // old lrc files + std::shared_ptr<Database> legacyDb; + try { + legacyDb = lrc::DatabaseFactory::create<LegacyDatabase>(appPath); + } catch (const std::runtime_error& e) { + qDebug() << "Exception while attempting to load legacy database: " << e.what(); + if (didMigrateCb) + didMigrateCb(); + return; + } + + // attempt to make a backup of ring.db + { + QFile dbFile(dataDir.absoluteFilePath("ring.db")); + if (dbFile.open(QIODevice::ReadOnly)) { + dbFile.copy(appPath + "ring.db.bak"); + } + } + + // 3. migrate db version 1.1 -> per account dbs version 1 + int index = 0; + for (const auto& accountId : accountIds) { + if (hasMigratedData.at(accountId)) { + index++; + continue; + } + qDebug() << "Migrating account: " << accountId << "..."; + // try to remove the transaction journal from a failed migration + QFile(appPath + accountId + "/history.db-journal").remove(); + try { + QSqlDatabase::database().transaction(); + auto dbName = QString::fromStdString(accountId.toStdString() + "/history"); + dbs.at(index) = lrc::DatabaseFactory::create<Database>(dbName, appPath); + auto& db = dbs.at(index++); + migration::migrateAccountDb(accountId, db, legacyDb); + QSqlDatabase::database().commit(); + } catch (const std::runtime_error& e) { + qWarning().noquote() << "Could not migrate database for account: " << accountId + << "\n " << e.what(); + QSqlDatabase::database().rollback(); + } + } + + // done + if (didMigrateCb) + didMigrateCb(); + }); + + // if willMigrateCb blocks, it must be unblocked by didMigrateCb + if (willMigrateCb) + willMigrateCb(); + + migrateThread.join(); + + return dbs; +} + +} // namespace storage + +} // namespace authority + +} // namespace lrc diff --git a/src/libclient/authority/storagehelper.h b/src/libclient/authority/storagehelper.h new file mode 100644 index 0000000000000000000000000000000000000000..a5060fd5cd71cd26eb59dd9a862f9b3b84097602 --- /dev/null +++ b/src/libclient/authority/storagehelper.h @@ -0,0 +1,374 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com> * + * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +// Lrc +#include "api/account.h" +#include "api/contact.h" +#include "api/conversation.h" +#include "api/interaction.h" +#include "database.h" +#include "dbus/configurationmanager.h" + +namespace lrc { + +namespace api { +namespace datatransfer { +struct Info; +} +} // namespace api + +namespace authority { + +namespace storage { + +/** + * Get the base path for the application's local storage + * @return local storage path + */ +QString getPath(); + +/** + * Get a formatted for local storage + * @param uri that may have a scheme prefixed + * @param type of account for which to transform the uri + * @return formatted uri + */ +QString prepareUri(const QString& uri, api::profile::Type type); + +/** + * Get a formatted string for a call interaction's body + * @param author_uri + * @param duration of the call + * @return the formatted and translated call message string + */ +QString getCallInteractionString(const QString& authorUri, const std::time_t& duration); + +/** + * Get a formatted string for a contact interaction's body + * @param author_uri + * @param status + * @return the formatted and translated call message string + */ +QString getContactInteractionString(const QString& authorUri, + const api::interaction::Status& status); + +namespace vcard { + +/** + * Build the vCard for a profile + * @param profileInfo + * @param compressImage + * @return vcard string of the profile + */ +QString profileToVcard(const api::profile::Info& profileInfo, bool compressImage = false); + +/** + * Set a profile vCard + * @param accountId + * @param profileInfo + * @param isPeer + */ +void setProfile(const QString& accountId, + const api::profile::Info& profileInfo, + const bool isPeer = false); + +} // namespace vcard + +/** + * @param duration + * @return a human readable call duration (M:ss) + */ +QString getFormattedCallDuration(const std::time_t duration); + +/** + * Get all conversations with a given participant's URI + * @param db + * @param participant_uri + */ +VectorString getConversationsWithPeer(Database& db, const QString& participant_uri); + +/** + * Get all peer participant(s) URIs for a given conversation id + * @param db + * @param conversationId + */ +VectorString getPeerParticipantsForConversation(Database& db, const QString& conversationId); + +/** + * Creates or updates a contact or account vCard file with profile data. + * @param accountId + * @param profileInfo the contact info containing peer profile information + * @param isPeer indicates that a the profileInfo is that of a peer + */ +void createOrUpdateProfile(const QString& accountId, + const api::profile::Info& profileInfo, + const bool isPeer = false); + +/** + * Remove a profile vCard + * @param accountId + * @param peerUri + */ +void removeProfile(const QString& accountId, const QString& peerUri); + +/** + * Gets the account's avatar from the profile.vcf file + * @param accountId + * @return the account's base64 avatar + */ +QString getAccountAvatar(const QString& accountId); + +/** + * Build a contact info struct from a vCard + * @param accountId + * @param peer_uri + * @param type of contact to build + * @return the contact info containing peer profile information + */ +api::contact::Info buildContactFromProfile(const QString& accountId, + const QString& peer_uri, + const api::profile::Type& type); + +/** + * Get a contact's avatar + * @param accountId + * @param contactUri + * @return the avatar + */ +QString avatar(const QString& accountId, const QString& contactUri = ""); + +/** + * Get all conversations for an account in the database. + * @param db + * @return conversations id for all conversations + */ +VectorString getAllConversations(Database& db); + +/** + * Get conversations shared between an account and a contact. + * @param db + * @param accountProfile the id of the account in the database + * @param contactProfile the id of the contact in the database + * @return conversations id for conversations between account and contact + */ +VectorString getConversationsBetween(Database& db, + const QString& accountProfile, + const QString& contactProfile); + +/** + * Start a conversation between account and contact. Creates an entry in the conversations table + * and an entry in the interactions table. + * @param db + * @param peer_uri the URI of the peer + * @param isOutgoing + * @param timestamp + * @return conversation_id of the new conversation. + */ +QString beginConversationWithPeer(Database& db, + const QString& peer_uri, + const bool isOutgoing = true, + time_t timestamp = 0); + +/** + * Return interactions from a conversation + * @param db + * @param conversation to modify + */ +void getHistory(Database& db, api::conversation::Info& conversation); + +/** + * Add an entry into interactions linked to a conversation. + * @param db + * @param conversationId + * @param msg + * @return the id of the inserted interaction + */ +QString addMessageToConversation(Database& db, + const QString& conversationId, + const api::interaction::Info& msg); + +/** + * Add or update an entry into interactions linked to a conversation. + * @param db + * @param conversationId + * @param msg + * @param daemonId + * @return the id of the inserted interaction + */ +QString addOrUpdateMessage(Database& db, + const QString& conversationId, + const api::interaction::Info& msg, + const QString& daemonId); + +/** + * Add a data transfer entry into interactions linked to a conversation. + * @param db + * @param conversationId + * @param daemonId + * @return the id of the inserted interaction + */ +QString addDataTransferToConversation(Database& db, + const QString& conversationId, + const api::datatransfer::Info& infoFromDaemon); + +/** + * Change the daemon_id column for an interaction + * @param db + * @param interactionId + * @param daemonId + */ +void addDaemonMsgId(Database& db, const QString& interactionId, const QString& daemonId); + +/** + * @param db + * @param id + * @return the daemon id for an interaction else an empty string + */ +QString getDaemonIdByInteractionId(Database& db, const QString& id); + +/** + * Obtain the id of an interaction of a given daemon_id + * @param db + * @param daemon id + * @return the interaction id for a daemon id else an empty string + */ +QString getInteractionIdByDaemonId(Database& db, const QString& daemon_id); + +/** + * Obtain the extra_data column of an interaction of a given id + * @note if a key is provided and exists, the value will be returned + * @param db + * @param id + * @param key + */ +QString getInteractionExtraDataById(Database& db, const QString& id, const QString& key = {}); + +/** + * update interaction + * @param db + * @param daemon id + * @param interaction + */ +void updateDataTransferInteractionForDaemonId(Database& db, + const QString& daemonId, + api::interaction::Info& interaction); + +/** + * Change the body of an interaction + * @param db + * @param id + * @param newBody + */ +void updateInteractionBody(Database& db, const QString& id, const QString& newBody); + +/** + * Change the status of an interaction + * @param db + * @param id + * @param newStatus + * @param isRead + */ +void updateInteractionStatus(Database& db, const QString& id, api::interaction::Status newStatus); + +/** + * Set interaction to the read state + * @param db + * @param id + */ +void setInteractionRead(Database& db, const QString& id); + +/** + * Clear history but not the conversation started interaction + * @param db + * @param conversationId + */ +void clearHistory(Database& db, const QString& conversationId); + +/** + * Clear interaction from history + * @param db + * @param conversationId + * @param interactionId + */ +void clearInteractionFromConversation(Database& db, + const QString& conversationId, + const QString& interactionId); + +/** + * Clear all history stored in the interactions table of the database + * @param db + */ +void clearAllHistory(Database& db); + +/** + * delete obsolete history from the database + * @param db + * @param date in second since epoch. Below this date, interactions will be deleted + */ +void deleteObsoleteHistory(Database& db, long int date); + +/** + * Remove all conversation with a contact. Remove corresponding entries in + * the conversations table. + * @param accountId + * @param db + * @param contactUri + */ +void removeContactConversations(Database& db, const QString& contactUri); + +/** + * count number of 'UNREAD' from 'interactions' table. + * @param db + * @param conversationId + */ +int countUnreadFromInteractions(Database& db, const QString& conversationId); + +/** + * Retrieve an interaction's conversation id + * @param db + * @param conversationId + */ +QString conversationIdFromInteractionId(Database& db, const QString& interactionId); + +/** + * Retrieve the last timestamp from the interactions table + * is used for ConfigurationManager::getLastMessages + * @param db + */ +uint64_t getLastTimestamp(Database& db); + +/** + * Retrieve a list of account database via a migration + * procedure from the legacy "ring.db", if it exists + * @param accountIds of the accounts to attempt migration upon + * @param willMigrateCb to invoke when migration will occur + * @param didMigrateCb to invoke when migration has completed + */ +std::vector<std::shared_ptr<Database>> migrateIfNeeded(const QStringList& accountIds, + MigrationCb& willMigrateCb, + MigrationCb& didMigrateCb); + +} // namespace storage + +} // namespace authority + +} // namespace lrc diff --git a/src/libclient/avmodel.cpp b/src/libclient/avmodel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f05b60ad5c5fda212144d02cbd72a38a53a1a104 --- /dev/null +++ b/src/libclient/avmodel.cpp @@ -0,0 +1,963 @@ +/* + * Copyright (C) 2018-2022 Savoir-faire Linux Inc. + * Author: Hugo Lefeuvre <hugo.lefeuvre@savoirfairelinux.com> + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "api/avmodel.h" + +#include "api/video.h" +#include "api/call.h" +#include "api/lrc.h" +#ifdef ENABLE_LIBWRAP +#include "directrenderer.h" +#else +#include "shmrenderer.h" +#endif +#include "callbackshandler.h" +#include "dbus/callmanager.h" +#include "dbus/configurationmanager.h" +#include "dbus/videomanager.h" +#include "authority/storagehelper.h" + +#include <media_const.h> + +#include <QtCore/QStandardPaths> +#include <QtCore/QDir> +#include <QUrl> +#include <QSize> + +#include <algorithm> // std::sort +#include <chrono> +#include <csignal> +#include <iomanip> // for std::put_time +#include <fstream> +#include <mutex> +#include <thread> +#include <string> +#include <sstream> + +#if defined(Q_OS_UNIX) && !defined(__APPLE__) +#include <xcb/xcb.h> +#endif + +namespace lrc { + +using namespace api; +using namespace api::video; +using namespace lrc::video; + +class AVModelPimpl : public QObject +{ + Q_OBJECT +public: + AVModelPimpl(AVModel& linked, const CallbacksHandler& callbacksHandler); + + const CallbacksHandler& callbacksHandler; + QString getRecordingPath() const; + static const QString recorderSavesSubdir; + AVModel& linked_; + + std::mutex renderers_mtx_; + std::map<QString, std::unique_ptr<Renderer>> renderers_; + QString currentVideoCaptureDevice_ {}; + +#ifndef ENABLE_LIBWRAP + // TODO: Init Video Renderers from daemon (see: + // https://git.jami.net/savoirfairelinux/ring-daemon/issues/59) + static void stopCameraAndQuit(int); + static uint32_t SIZE_RENDERER; +#endif + + /** + * Get device via its type + * @param type + * @return the device name + */ + QString getDevice(int type) const; + + /** + * Add video::Renderer to renderers_ and start it + * @param id + * @param size + * @param shmPath + */ + void addRenderer(const QString& id, const QSize& res, const QString& shmPath = {}); + + /** + * Remove renderer from renderers_ + * @param id + */ + void removeRenderer(const QString& id); + + bool hasRenderer(const QString& id); + QSize getRendererSize(const QString& id); + Frame getRendererFrame(const QString& id); + +public Q_SLOTS: + /** + * Listen from CallbacksHandler when a renderer starts + * @param id + * @param shmPath + * @param width + * @param height + */ + void onDecodingStarted(const QString& id, const QString& shmPath, int width, int height); + /** + * Listen from CallbacksHandler when a renderer stops + * @param id + * @param shmPath + */ + void onDecodingStopped(const QString& id, const QString& shmPath); + /** + * Detect when a video device is plugged or unplugged + */ + void slotDeviceEvent(); + /** + * Detect when an audio device is plugged or unplugged + */ + void slotAudioDeviceEvent(); + /** + * Audio volume level + * @param id Ringbuffer id + * @param level Volume in range [0, 1] + */ + void slotAudioMeter(const QString& id, float level); + /** + * Listen from CallbacksHandler when a recorder stopped notice is incoming + * @param filePath + */ + void slotRecordPlaybackStopped(const QString& filePath); +}; + +const QString AVModelPimpl::recorderSavesSubdir = "sent_data"; +#ifndef ENABLE_LIBWRAP +uint32_t AVModelPimpl::SIZE_RENDERER = 0; +#endif + +AVModel::AVModel(const CallbacksHandler& callbacksHandler) + : QObject(nullptr) + , pimpl_(std::make_unique<AVModelPimpl>(*this, callbacksHandler)) +{ +#ifndef ENABLE_LIBWRAP + // Because the client uses DBUS, if a crash occurs, the daemon will not + // be able to know it. So, stop the camera if the user was just previewing. + std::signal(SIGSEGV, AVModelPimpl::stopCameraAndQuit); + std::signal(SIGINT, AVModelPimpl::stopCameraAndQuit); +#endif +} + +AVModel::~AVModel() +{ + std::lock_guard<std::mutex> lk(pimpl_->renderers_mtx_); + for (auto r = pimpl_->renderers_.begin(); r != pimpl_->renderers_.end(); ++r) { + (*r).second.reset(); + } +} + +bool +AVModel::getDecodingAccelerated() const +{ + bool result = VideoManager::instance().getDecodingAccelerated(); + return result; +} + +void +AVModel::setDecodingAccelerated(bool accelerate) +{ + VideoManager::instance().setDecodingAccelerated(accelerate); +} + +bool +AVModel::getEncodingAccelerated() const +{ + bool result = VideoManager::instance().getEncodingAccelerated(); + return result; +} + +void +AVModel::setEncodingAccelerated(bool accelerate) +{ + VideoManager::instance().setEncodingAccelerated(accelerate); +} + +bool +AVModel::getHardwareAcceleration() const +{ + bool result = getDecodingAccelerated() & getEncodingAccelerated(); + return result; +} +void +AVModel::setHardwareAcceleration(bool accelerate) +{ + setDecodingAccelerated(accelerate); + setEncodingAccelerated(accelerate); +} + +QVector<QString> +AVModel::getDevices() const +{ + QStringList devices = VideoManager::instance().getDeviceList(); + VectorString result; + for (const auto& device : devices) { + result.push_back(device); + } + return (QVector<QString>) result; +} + +QString +AVModel::getDefaultDevice() const +{ + return VideoManager::instance().getDefaultDevice(); +} + +void +AVModel::setDefaultDevice(const QString& deviceId) +{ + VideoManager::instance().setDefaultDevice(deviceId); +} + +Settings +AVModel::getDeviceSettings(const QString& deviceId) const +{ + if (deviceId.isEmpty()) { + return video::Settings(); + } + MapStringString settings = VideoManager::instance().getSettings(deviceId); + if (settings["id"] != deviceId) { + throw std::out_of_range("Device '" + deviceId.toStdString() + "' not found"); + } + video::Settings result; + result.name = settings["name"]; + result.id = settings["id"]; + result.channel = settings["channel"]; + result.size = settings["size"]; + result.rate = settings["rate"].toFloat(); + return result; +} + +Capabilities +AVModel::getDeviceCapabilities(const QString& deviceId) const +{ + // Channel x Resolution x Framerate + QMap<QString, QMap<QString, QVector<QString>>> capabilites = VideoManager::instance() + .getCapabilities(deviceId); + video::Capabilities result; + for (auto& channel : capabilites.toStdMap()) { + video::ResRateList channelCapabilities; + for (auto& resToRates : channel.second.toStdMap()) { + video::FrameratesList rates; + QVectorIterator<QString> itRates(resToRates.second); + while (itRates.hasNext()) { + rates.push_back(itRates.next().toFloat()); + } + std::sort(rates.begin(), rates.end(), std::greater<int>()); + channelCapabilities.push_back(qMakePair(resToRates.first, rates)); + } + // sort by resolution widths + std::sort(channelCapabilities.begin(), + channelCapabilities.end(), + [](const QPair<video::Resolution, video::FrameratesList>& lhs, + const QPair<video::Resolution, video::FrameratesList>& rhs) { + auto lhsWidth = lhs.first.left(lhs.first.indexOf("x")).toLongLong(); + auto rhsWidth = rhs.first.left(rhs.first.indexOf("x")).toLongLong(); + return lhsWidth > rhsWidth; + }); + result.insert(channel.first, channelCapabilities); + } + return result; +} + +void +AVModel::setDeviceSettings(video::Settings& settings) +{ + MapStringString newSettings; + auto rate = QString::number(settings.rate, 'f', 7); + rate = rate.left(rate.length() - 1); + newSettings["channel"] = settings.channel; + newSettings["name"] = settings.name; + newSettings["id"] = settings.id; + newSettings["rate"] = rate; + newSettings["size"] = settings.size; + VideoManager::instance().applySettings(settings.id, newSettings); + + // If the preview is running, reload it + // doing this during a call will cause re-invite, this is unwanted + std::unique_lock<std::mutex> lk(pimpl_->renderers_mtx_); + auto it = pimpl_->renderers_.find(video::PREVIEW_RENDERER_ID); + if (it != pimpl_->renderers_.end() && it->second && pimpl_->renderers_.size() == 1) { + lk.unlock(); + stopPreview(video::PREVIEW_RENDERER_ID); + startPreview(video::PREVIEW_RENDERER_ID); + } +} + +QString +AVModel::getDeviceIdFromName(const QString& deviceName) const +{ + auto devices = getDevices(); + auto iter = std::find_if(devices.begin(), devices.end(), [this, deviceName](const QString& d) { + auto settings = getDeviceSettings(d); + return settings.name == deviceName; + }); + if (iter == devices.end()) { + qWarning() << "Couldn't find device: " << deviceName; + return {}; + } + return *iter; +} + +VectorString +AVModel::getSupportedAudioManagers() const +{ + QStringList managers = ConfigurationManager::instance().getSupportedAudioManagers(); + VectorString result; + for (const auto& manager : managers) { + result.push_back(manager); + } + return result; +} + +QString +AVModel::getAudioManager() const +{ + return ConfigurationManager::instance().getAudioManager(); +} + +QVector<QString> +AVModel::getAudioOutputDevices() const +{ + QStringList devices = ConfigurationManager::instance().getAudioOutputDeviceList(); + + // A fix for ring-daemon#43 + if (ConfigurationManager::instance().getAudioManager() == QStringLiteral("pulseaudio")) { + if (devices.at(0) == QStringLiteral("default")) { + devices[0] = QObject::tr("default"); + } + } + + VectorString result; + for (const auto& device : devices) { + result.push_back(device); + } + return (QVector<QString>) result; +} + +QVector<QString> +AVModel::getAudioInputDevices() const +{ + QStringList devices = ConfigurationManager::instance().getAudioInputDeviceList(); + + // A fix for ring-daemon#43 + if (ConfigurationManager::instance().getAudioManager() == QStringLiteral("pulseaudio")) { + if (devices.at(0) == QStringLiteral("default")) { + devices[0] = QObject::tr("default"); + } + } + + VectorString result; + for (const auto& device : devices) { + result.push_back(device); + } + return (QVector<QString>) result; +} + +QString +AVModel::getRingtoneDevice() const +{ + const int RINGTONE_IDX = 2; + return pimpl_->getDevice(RINGTONE_IDX); +} + +QString +AVModel::getOutputDevice() const +{ + const int OUTPUT_IDX = 0; + return pimpl_->getDevice(OUTPUT_IDX); +} + +QString +AVModel::getInputDevice() const +{ + const int INPUT_IDX = 1; + return pimpl_->getDevice(INPUT_IDX); +} + +bool +AVModel::isAudioMeterActive(const QString& id) const +{ + return ConfigurationManager::instance().isAudioMeterActive(id); +} + +void +AVModel::setAudioMeterState(bool active, const QString& id) const +{ + ConfigurationManager::instance().setAudioMeterState(id, active); +} + +void +AVModel::startAudioDevice() const +{ + VideoManager::instance().startAudioDevice(); +} + +void +AVModel::stopAudioDevice() const +{ + VideoManager::instance().stopAudioDevice(); +} + +bool +AVModel::setAudioManager(const QString& name) +{ + return ConfigurationManager::instance().setAudioManager(name); +} + +void +AVModel::setRingtoneDevice(const QString& name) +{ + int idx = ConfigurationManager::instance().getAudioOutputDeviceIndex(name); + ConfigurationManager::instance().setAudioRingtoneDevice(idx); +} + +void +AVModel::setOutputDevice(const QString& name) +{ + int idx = ConfigurationManager::instance().getAudioOutputDeviceIndex(name); + ConfigurationManager::instance().setAudioOutputDevice(idx); +} + +void +AVModel::setInputDevice(const QString& name) +{ + int idx = ConfigurationManager::instance().getAudioInputDeviceIndex(name); + ConfigurationManager::instance().setAudioInputDevice(idx); +} + +void +AVModel::stopLocalRecorder(const QString& path) const +{ + if (path.isEmpty()) { + qWarning("stopLocalRecorder: can't stop non existing recording"); + return; + } + + VideoManager::instance().stopLocalRecorder(path); +} + +QString +AVModel::startLocalMediaRecorder(const QString& videoInputId) const +{ + const QString path = pimpl_->getRecordingPath(); + const QString finalPath = VideoManager::instance().startLocalMediaRecorder(videoInputId, path); + return finalPath; +} + +QString +AVModel::getRecordPath() const +{ + return ConfigurationManager::instance().getRecordPath(); +} + +void +AVModel::setRecordPath(const QString& path) const +{ + ConfigurationManager::instance().setRecordPath(path.toUtf8()); +} + +bool +AVModel::getAlwaysRecord() const +{ + return ConfigurationManager::instance().getIsAlwaysRecording(); +} + +void +AVModel::setAlwaysRecord(const bool& rec) const +{ + ConfigurationManager::instance().setIsAlwaysRecording(rec); +} + +bool +AVModel::getRecordPreview() const +{ + return ConfigurationManager::instance().getRecordPreview(); +} + +void +AVModel::setRecordPreview(const bool& rec) const +{ + ConfigurationManager::instance().setRecordPreview(rec); +} + +int +AVModel::getRecordQuality() const +{ + return ConfigurationManager::instance().getRecordQuality(); +} + +void +AVModel::setRecordQuality(const int& rec) const +{ + ConfigurationManager::instance().setRecordQuality(rec); +} + +QString +AVModel::startPreview(const QString& resource) +{ + return VideoManager::instance().openVideoInput(resource); +} + +void +AVModel::stopPreview(const QString& resource) +{ + VideoManager::instance().closeVideoInput(resource); +} + +#if defined(Q_OS_UNIX) && !defined(__APPLE__) +static xcb_atom_t +getAtom(xcb_connection_t* c, const std::string& atomName) +{ + xcb_intern_atom_cookie_t atom_cookie = xcb_intern_atom(c, 0, atomName.size(), atomName.c_str()); + if (auto* rep = xcb_intern_atom_reply(c, atom_cookie, nullptr)) { + xcb_atom_t atom = rep->atom; + free(rep); + return atom; + } + return {}; +} +#endif + +const QVariantMap +AVModel::getListWindows() const +{ + QMap<QString, QVariant> ret {}; + +#if defined(Q_OS_UNIX) && !defined(__APPLE__) + std::unique_ptr<xcb_connection_t, void (*)(xcb_connection_t*)> c(xcb_connect(nullptr, nullptr), + [](xcb_connection_t* ptr) { + xcb_disconnect(ptr); + }); + + if (xcb_connection_has_error(c.get())) { + qDebug() << "xcb connection has error"; + return ret; + } + + auto atomNetClient = getAtom(c.get(), "_NET_CLIENT_LIST"); + auto atomWMVisibleName = getAtom(c.get(), "_NET_WM_NAME"); + if (!atomNetClient || !atomWMVisibleName) + return ret; + + auto* screen = xcb_setup_roots_iterator(xcb_get_setup(c.get())).data; + + xcb_get_property_cookie_t propCookieList = xcb_get_property(c.get(), + 0, + screen->root, + atomNetClient, + XCB_GET_PROPERTY_TYPE_ANY, + 0, + 100); + + using propertyPtr + = std::unique_ptr<xcb_get_property_reply_t, void (*)(xcb_get_property_reply_t*)>; + + xcb_generic_error_t* e; + propertyPtr replyPropList(xcb_get_property_reply(c.get(), propCookieList, &e), + [](auto* ptr) { free(ptr); }); + if (e) { + qDebug() << "Error: " << e->error_code; + free(e); + } + if (replyPropList.get()) { + int valueLegth = xcb_get_property_value_length(replyPropList.get()); + if (valueLegth) { + auto* win = static_cast<xcb_window_t*>(xcb_get_property_value(replyPropList.get())); + for (int i = 0; i < valueLegth / 4; i++) { + xcb_get_property_cookie_t prop_cookie = xcb_get_property(c.get(), + 0, + win[i], + atomWMVisibleName, + XCB_GET_PROPERTY_TYPE_ANY, + 0, + 1000); + propertyPtr replyProp {xcb_get_property_reply(c.get(), prop_cookie, &e), + [](auto* ptr) { + free(ptr); + }}; + if (e) { + qDebug() << "Error: " << e->error_code; + free(e); + } + if (replyProp.get()) { + int valueLegth2 = xcb_get_property_value_length(replyProp.get()); + if (valueLegth2) { + auto name = QString::fromUtf8( + reinterpret_cast<char*>(xcb_get_property_value(replyProp.get()))); + name.truncate(valueLegth2); + if (ret.find(name) != ret.end()) + name += QString(" - 0x%1").arg(win[i], 0, 16); + ret.insert(name, QVariant(QString("0x%1").arg(win[i], 0, 16))); + } + } + } + } + } + return ret; +#else + return ret; +#endif +} + +void +AVModel::setCurrentVideoCaptureDevice(const QString& currentVideoCaptureDevice) +{ + pimpl_->currentVideoCaptureDevice_ = currentVideoCaptureDevice; +} + +QString +AVModel::getCurrentVideoCaptureDevice() const +{ + return pimpl_->currentVideoCaptureDevice_; +} + +void +AVModel::clearCurrentVideoCaptureDevice() +{ + pimpl_->currentVideoCaptureDevice_.clear(); +} + +void +AVModel::addRenderer(const QString& id, const QSize& res, const QString& shmPath) +{ + pimpl_->addRenderer(id, res, shmPath); +} + +bool +AVModel::hasRenderer(const QString& id) +{ + return pimpl_->hasRenderer(id); +} + +QSize +AVModel::getRendererSize(const QString& id) +{ + return pimpl_->getRendererSize(id); +} + +Frame +AVModel::getRendererFrame(const QString& id) +{ + return pimpl_->getRendererFrame(id); +} + +bool +AVModel::useDirectRenderer() const +{ +#ifdef ENABLE_LIBWRAP + return true; +#else + return false; +#endif +} + +AVModelPimpl::AVModelPimpl(AVModel& linked, const CallbacksHandler& callbacksHandler) + : callbacksHandler(callbacksHandler) + , linked_(linked) +{ + std::srand(std::time(nullptr)); +#ifndef ENABLE_LIBWRAP + SIZE_RENDERER = renderers_.size(); +#endif + connect(&callbacksHandler, &CallbacksHandler::deviceEvent, this, &AVModelPimpl::slotDeviceEvent); + connect(&callbacksHandler, + &CallbacksHandler::audioDeviceEvent, + this, + &AVModelPimpl::slotAudioDeviceEvent); + connect(&callbacksHandler, &CallbacksHandler::audioMeter, this, &AVModelPimpl::slotAudioMeter); + connect(&callbacksHandler, + &CallbacksHandler::recordPlaybackStopped, + this, + &AVModelPimpl::slotRecordPlaybackStopped); + + // render connections + connect(&callbacksHandler, + &CallbacksHandler::decodingStarted, + this, + &AVModelPimpl::onDecodingStarted); + connect(&callbacksHandler, + &CallbacksHandler::decodingStopped, + this, + &AVModelPimpl::onDecodingStopped); + + auto startedPreview = false; + auto restartRenderers = [&](const QStringList& callList) { + for (const auto& callId : callList) { + MapStringString rendererInfos = VideoManager::instance().getRenderer(callId); + auto shmPath = rendererInfos[DRing::Media::Details::SHM_PATH]; + auto width = rendererInfos[DRing::Media::Details::WIDTH].toInt(); + auto height = rendererInfos[DRing::Media::Details::HEIGHT].toInt(); + if (width > 0 && height > 0) { + startedPreview = true; + onDecodingStarted(callId, shmPath, width, height); + } + } + }; + restartRenderers(CallManager::instance().getCallList("")); + auto confIds = lrc::api::Lrc::getConferences(); + QStringList list; + Q_FOREACH (QString confId, confIds) { + list << confId; + } + restartRenderers(list); + if (startedPreview) + restartRenderers({"local"}); + currentVideoCaptureDevice_ = VideoManager::instance().getDefaultDevice(); +} + +QString +AVModelPimpl::getRecordingPath() const +{ + const QDir dir = authority::storage::getPath() + "/" + recorderSavesSubdir; + dir.mkpath("."); + + std::chrono::time_point<std::chrono::system_clock> time_now = std::chrono::system_clock::now(); + std::time_t time_now_t = std::chrono::system_clock::to_time_t(time_now); + std::tm now_tm = *std::localtime(&time_now_t); + + std::stringstream ss; + ss << dir.path().toStdString(); + ss << "/"; + ss << std::put_time(&now_tm, "%Y%m%d-%H%M%S"); + ss << "-"; + ss << std::rand(); + + QDir file_path(ss.str().c_str()); + + return file_path.path(); +} + +void +AVModelPimpl::onDecodingStarted(const QString& id, const QString& shmPath, int width, int height) +{ + if (id != "" && id != "local" && !id.contains("://")) // Else managed by callmodel + return; + addRenderer(id, QSize(width, height), shmPath); +} + +void +AVModelPimpl::onDecodingStopped(const QString& id, const QString& shmPath) +{ + Q_UNUSED(shmPath) + removeRenderer(id); +} + +#ifndef ENABLE_LIBWRAP +void +AVModelPimpl::stopCameraAndQuit(int) +{ + if (SIZE_RENDERER == 1) { + // This will stop the preview if needed (not in a call). + VideoManager::instance().closeVideoInput(PREVIEW_RENDERER_ID); + // HACK: this sleep is just here to let the camera stop and + // avoid immediate raise + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + } + std::raise(SIGTERM); +} + +#endif +QString +AVModelPimpl::getDevice(int type) const +{ + if (type < 0 || type > 2) + return {}; // No device + QString result = ""; + VectorString devices; + switch (type) { + case 1: // INPUT + devices = linked_.getAudioInputDevices(); + break; + case 0: // OUTPUT + case 2: // RINGTONE + devices = linked_.getAudioOutputDevices(); + break; + default: + break; + } + QStringList currentDevicesIdx = ConfigurationManager::instance().getCurrentAudioDevicesIndex(); + try { + if (currentDevicesIdx.size() < 3) { + // Should not happen, but cannot retrieve current ringtone device + return ""; + } + auto deviceIdx = currentDevicesIdx[type].toInt(); + for (const auto& dev : devices) { + int idx {-1}; + switch (type) { + case 1: // INPUT + idx = ConfigurationManager::instance().getAudioInputDeviceIndex(dev); + break; + case 0: // OUTPUT + case 2: // RINGTONE + idx = ConfigurationManager::instance().getAudioOutputDeviceIndex(dev); + break; + default: + break; + } + if (idx == deviceIdx) { + return dev; + } + } + return ""; + } catch (std::bad_alloc& ba) { + qWarning() << "bad_alloc caught: " << ba.what(); + return ""; + } + return result; +} + +static std::unique_ptr<Renderer> +createRenderer(const QString& id, const QSize& res, const QString& shmPath = {}) +{ +#ifdef ENABLE_LIBWRAP + Q_UNUSED(shmPath) + return std::make_unique<DirectRenderer>(id, res); +#else + return std::make_unique<ShmRenderer>(id, res, shmPath); +#endif +} + +void +AVModelPimpl::addRenderer(const QString& id, const QSize& res, const QString& shmPath) +{ + { + auto connectRenderer = [this](Renderer* renderer, const QString& id) { + connect( + renderer, + &Renderer::started, + this, + [this, id] { Q_EMIT linked_.rendererStarted(id); }, + Qt::QueuedConnection); + connect( + renderer, + &Renderer::frameBufferRequested, + this, + [this, id](AVFrame* frame) { Q_EMIT linked_.frameBufferRequested(id, frame); }, + Qt::DirectConnection); + connect( + renderer, + &Renderer::frameUpdated, + this, + [this, id] { Q_EMIT linked_.frameUpdated(id); }, + Qt::DirectConnection); + connect( + renderer, + &Renderer::stopped, + this, + [this, id] { Q_EMIT linked_.rendererStopped(id); }, + Qt::DirectConnection); + }; + std::lock_guard<std::mutex> lk(renderers_mtx_); + Renderer* renderer {nullptr}; + auto it = renderers_.find(id); + if (it == renderers_.end()) { + renderers_.emplace(id, createRenderer(id, res, shmPath)); + renderer = renderers_.at(id).get(); + connectRenderer(renderer, id); + renderer->startRendering(); + } else { + renderer = it->second.get(); + if (renderer) { + renderer->update(res, shmPath); + } else { + it->second.reset(createRenderer(id, res, shmPath).get()); + renderer = it->second.get(); + connectRenderer(renderer, id); + renderer->startRendering(); + } + } + } +} + +void +AVModelPimpl::removeRenderer(const QString& id) +{ + std::lock_guard<std::mutex> lk(renderers_mtx_); + auto it = renderers_.find(id); + if (it == renderers_.end()) { + qWarning() << "Cannot remove renderer. " << id << "not found"; + return; + } + renderers_.erase(id); +} + +bool +AVModelPimpl::hasRenderer(const QString& id) +{ + std::lock_guard<std::mutex> lk(renderers_mtx_); + return renderers_.find(id) != renderers_.end(); +} + +QSize +AVModelPimpl::getRendererSize(const QString& id) +{ + std::lock_guard<std::mutex> lk(renderers_mtx_); + auto it = renderers_.find(id); + if (it != renderers_.end()) { + return it->second->size(); + } + return {}; +} + +Frame +AVModelPimpl::getRendererFrame(const QString& id) +{ + std::lock_guard<std::mutex> lk(renderers_mtx_); + auto it = renderers_.find(id); + if (it != renderers_.end()) { + return it->second->currentFrame(); + } + return {}; +} + +void +AVModelPimpl::slotDeviceEvent() +{ + Q_EMIT linked_.deviceEvent(); +} + +void +AVModelPimpl::slotAudioDeviceEvent() +{ + Q_EMIT linked_.audioDeviceEvent(); +} + +void +AVModelPimpl::slotAudioMeter(const QString& id, float level) +{ + Q_EMIT linked_.audioMeter(id, level); +} + +void +AVModelPimpl::slotRecordPlaybackStopped(const QString& filePath) +{ + Q_EMIT linked_.recordPlaybackStopped(filePath); +} + +} // namespace lrc + +#include "api/moc_avmodel.cpp" +#include "avmodel.moc" diff --git a/src/libclient/behaviorcontroller.cpp b/src/libclient/behaviorcontroller.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ce7fd2260de98ca4b9c1133952a9f05a134af0a0 --- /dev/null +++ b/src/libclient/behaviorcontroller.cpp @@ -0,0 +1,36 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#include "api/behaviorcontroller.h" + +// Models and database +#include "api/lrc.h" + +namespace lrc { + +using namespace api; + +BehaviorController::BehaviorController() + : QObject(nullptr) +{} + +BehaviorController::~BehaviorController() {} + +} // namespace lrc + +#include "api/moc_behaviorcontroller.cpp" diff --git a/src/libclient/callbackshandler.cpp b/src/libclient/callbackshandler.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3a22e69918092ad0d2f5f57d78bff6b58175a610 --- /dev/null +++ b/src/libclient/callbackshandler.cpp @@ -0,0 +1,782 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#include "callbackshandler.h" + +// Models and database +#include "api/account.h" +#include "api/lrc.h" +#include "api/newaccountmodel.h" +#include "api/datatransfer.h" +#include "api/datatransfermodel.h" +#include "api/behaviorcontroller.h" + +// Lrc +#include "dbus/callmanager.h" +#include "dbus/configurationmanager.h" +#include "dbus/presencemanager.h" +#include "dbus/videomanager.h" + +// DRing +#include <datatransfer_interface.h> + +#include <QFileInfo> + +#ifdef ENABLE_LIBWRAP +// For the debugMessageReceived connection that queues const std::string refs +// when not using dbus +Q_DECLARE_METATYPE(std::string); +#endif + +namespace lrc { + +using namespace api; + +static inline datatransfer::Status +convertDataTransferEvent(DRing::DataTransferEventCode event) +{ + switch (event) { + case DRing::DataTransferEventCode::invalid: + return datatransfer::Status::INVALID; + case DRing::DataTransferEventCode::created: + return datatransfer::Status::on_connection; + case DRing::DataTransferEventCode::unsupported: + return datatransfer::Status::unsupported; + case DRing::DataTransferEventCode::wait_peer_acceptance: + return datatransfer::Status::on_connection; + case DRing::DataTransferEventCode::wait_host_acceptance: + return datatransfer::Status::on_connection; + case DRing::DataTransferEventCode::ongoing: + return datatransfer::Status::on_progress; + case DRing::DataTransferEventCode::finished: + return datatransfer::Status::success; + case DRing::DataTransferEventCode::closed_by_host: + return datatransfer::Status::stop_by_host; + case DRing::DataTransferEventCode::closed_by_peer: + return datatransfer::Status::stop_by_peer; + case DRing::DataTransferEventCode::invalid_pathname: + return datatransfer::Status::invalid_pathname; + case DRing::DataTransferEventCode::unjoinable_peer: + return datatransfer::Status::unjoinable_peer; + case DRing::DataTransferEventCode::timeout_expired: + return datatransfer::Status::timeout_expired; + } + throw std::runtime_error("BUG: broken convertDataTransferEvent() switch"); +} + +CallbacksHandler::CallbacksHandler(const Lrc& parent) + : QObject() + , parent(parent) +{ + // Get signals from daemon + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::incomingAccountMessage, + this, + &CallbacksHandler::slotNewAccountMessage, + Qt::QueuedConnection); + + connect(&PresenceManager::instance(), + &PresenceManagerInterface::newBuddyNotification, + this, + &CallbacksHandler::slotNewBuddySubscription, + Qt::QueuedConnection); + + connect(&PresenceManager::instance(), + &PresenceManagerInterface::nearbyPeerNotification, + this, + &CallbacksHandler::slotNearbyPeerSubscription, + Qt::QueuedConnection); + + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::contactAdded, + this, + &CallbacksHandler::slotContactAdded, + Qt::QueuedConnection); + + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::contactRemoved, + this, + &CallbacksHandler::slotContactRemoved, + Qt::QueuedConnection); + + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::incomingTrustRequest, + this, + &CallbacksHandler::slotIncomingContactRequest, + Qt::QueuedConnection); + + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::accountMessageStatusChanged, + this, + &CallbacksHandler::slotAccountMessageStatusChanged, + Qt::QueuedConnection); + + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::accountDetailsChanged, + this, + &CallbacksHandler::slotAccountDetailsChanged, + Qt::QueuedConnection); + + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::volatileAccountDetailsChanged, + this, + &CallbacksHandler::slotVolatileAccountDetailsChanged, + Qt::QueuedConnection); + + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::accountsChanged, + this, + &CallbacksHandler::slotAccountsChanged); + + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::registrationStateChanged, + this, + &CallbacksHandler::slotRegistrationStateChanged, + Qt::QueuedConnection); + + connect(&CallManager::instance(), + &CallManagerInterface::incomingCall, + this, + &CallbacksHandler::slotIncomingCall, + Qt::QueuedConnection); + + connect(&CallManager::instance(), + &CallManagerInterface::incomingCallWithMedia, + this, + &CallbacksHandler::slotIncomingCallWithMedia, + Qt::QueuedConnection); + + connect(&CallManager::instance(), + &CallManagerInterface::mediaChangeRequested, + this, + &CallbacksHandler::slotMediaChangeRequested, + Qt::QueuedConnection); + + connect(&CallManager::instance(), + &CallManagerInterface::callStateChanged, + this, + &CallbacksHandler::slotCallStateChanged, + Qt::QueuedConnection); + + connect(&CallManager::instance(), + &CallManagerInterface::mediaNegotiationStatus, + this, + &CallbacksHandler::slotMediaNegotiationStatus, + Qt::QueuedConnection); + + connect(&CallManager::instance(), + &CallManagerInterface::conferenceCreated, + this, + &CallbacksHandler::slotConferenceCreated, + Qt::QueuedConnection); + + connect(&CallManager::instance(), + &CallManagerInterface::conferenceRemoved, + this, + &CallbacksHandler::slotConferenceRemoved, + Qt::QueuedConnection); + + connect(&CallManager::instance(), + &CallManagerInterface::conferenceChanged, + this, + &CallbacksHandler::slotConferenceChanged, + Qt::QueuedConnection); + + connect(&CallManager::instance(), + &CallManagerInterface::incomingMessage, + this, + &CallbacksHandler::slotIncomingMessage, + Qt::QueuedConnection); + + connect(&CallManager::instance(), + &CallManagerInterface::recordPlaybackStopped, + this, + &CallbacksHandler::slotRecordPlaybackStopped, + Qt::QueuedConnection); + + connect(&CallManager::instance(), + &CallManagerInterface::voiceMailNotify, + this, + &CallbacksHandler::slotVoiceMailNotify, + Qt::QueuedConnection); + + connect(&CallManager::instance(), + &CallManagerInterface::remoteRecordingChanged, + this, + &CallbacksHandler::slotRemoteRecordingChanged, + Qt::QueuedConnection); + + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::dataTransferEvent, + this, + &CallbacksHandler::slotDataTransferEvent, + Qt::QueuedConnection); + + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::knownDevicesChanged, + this, + &CallbacksHandler::slotKnownDevicesChanged, + Qt::QueuedConnection); + + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::deviceRevocationEnded, + this, + &CallbacksHandler::slotDeviceRevokationEnded, + Qt::QueuedConnection); + + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::accountProfileReceived, + this, + &CallbacksHandler::slotAccountProfileReceived, + Qt::QueuedConnection); + + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::exportOnRingEnded, + this, + &CallbacksHandler::slotExportOnRingEnded, + Qt::QueuedConnection); + + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::nameRegistrationEnded, + this, + &CallbacksHandler::slotNameRegistrationEnded, + Qt::QueuedConnection); + + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::registeredNameFound, + this, + &CallbacksHandler::slotRegisteredNameFound, + Qt::QueuedConnection); + + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::migrationEnded, + this, + &CallbacksHandler::slotMigrationEnded, + Qt::QueuedConnection); + + connect(&VideoManager::instance(), + &VideoManagerInterface::decodingStarted, + this, + &CallbacksHandler::decodingStarted, + Qt::QueuedConnection); + + connect(&VideoManager::instance(), + &VideoManagerInterface::decodingStopped, + this, + &CallbacksHandler::decodingStopped, + Qt::QueuedConnection); + + connect(&VideoManager::instance(), + &VideoManagerInterface::deviceEvent, + this, + &CallbacksHandler::deviceEvent, + Qt::QueuedConnection); + + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::audioDeviceEvent, + this, + &CallbacksHandler::slotAudioDeviceEvent, + Qt::QueuedConnection); + + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::audioMeter, + this, + &CallbacksHandler::slotAudioMeterReceived, + Qt::QueuedConnection); + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::conversationLoaded, + this, + &CallbacksHandler::slotConversationLoaded, + Qt::QueuedConnection); + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::messageReceived, + this, + &CallbacksHandler::slotMessageReceived, + Qt::QueuedConnection); + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::conversationRequestReceived, + this, + &CallbacksHandler::slotConversationRequestReceived, + Qt::QueuedConnection); + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::conversationRequestDeclined, + this, + &CallbacksHandler::slotConversationRequestDeclined, + Qt::QueuedConnection); + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::conversationReady, + this, + &CallbacksHandler::slotConversationReady, + Qt::QueuedConnection); + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::conversationRemoved, + this, + &CallbacksHandler::slotConversationRemoved, + Qt::QueuedConnection); + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::conversationMemberEvent, + this, + &CallbacksHandler::slotConversationMemberEvent, + Qt::QueuedConnection); +} + +CallbacksHandler::~CallbacksHandler() {} + +void +CallbacksHandler::subscribeToDebugReceived() +{ + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::messageSend, + this, + &CallbacksHandler::slotDebugMessageReceived, + Qt::QueuedConnection); +} + +void +CallbacksHandler::slotNewAccountMessage(const QString& accountId, + const QString& peerId, + const QString& msgId, + const MapStringString& payloads) +{ + auto peerId2 = QString(peerId).replace("@ring.dht", ""); + Q_EMIT newAccountMessage(accountId, peerId2, msgId, payloads); +} + +void +CallbacksHandler::slotNewBuddySubscription(const QString& accountId, + const QString& uri, + bool status, + const QString& message) +{ + Q_UNUSED(status) + Q_UNUSED(message) + Q_EMIT newBuddySubscription(accountId, uri, status); +} + +void +CallbacksHandler::slotNearbyPeerSubscription(const QString& accountId, + const QString& contactUri, + int state, + const QString& displayname) +{ + Q_EMIT newPeerSubscription(accountId, contactUri, state, displayname); +} + +void +CallbacksHandler::slotVoiceMailNotify(const QString& accountId, + int newCount, + int oldCount, + int urgentCount) +{ + Q_EMIT voiceMailNotify(accountId, newCount, oldCount, urgentCount); +} + +void +CallbacksHandler::slotRecordPlaybackStopped(const QString& filePath) +{ + Q_EMIT recordPlaybackStopped(filePath); +} + +void +CallbacksHandler::slotContactAdded(const QString& accountId, + const QString& contactUri, + bool confirmed) +{ + Q_EMIT contactAdded(accountId, contactUri, confirmed); +} + +void +CallbacksHandler::slotContactRemoved(const QString& accountId, + const QString& contactUri, + bool banned) +{ + Q_EMIT contactRemoved(accountId, contactUri, banned); +} + +void +CallbacksHandler::slotIncomingContactRequest(const QString& accountId, + const QString& conversationId, + const QString& contactUri, + const QByteArray& payload, + time_t time) +{ + Q_UNUSED(time) + Q_EMIT incomingContactRequest(accountId, conversationId, contactUri, payload); +} + +void +CallbacksHandler::slotIncomingCall(const QString& accountId, + const QString& callId, + const QString& fromUri) +{ + slotIncomingCallWithMedia(accountId, callId, fromUri, {}); +} + +void +CallbacksHandler::slotIncomingCallWithMedia(const QString& accountId, + const QString& callId, + const QString& fromUri, + const VectorMapStringString& mediaList) +{ + QString displayname; + QString fromQString; + if (fromUri.contains("ring.dht")) { + auto qDisplayname = fromUri.left(fromUri.indexOf("<") + 1); + if (qDisplayname.size() > 2) { + displayname = qDisplayname.left(qDisplayname.indexOf("<") - 1); + } + fromQString = fromUri.right(50); + fromQString = fromQString.left(40); + } else { + auto left = fromUri.indexOf("<") + 1; + auto right = fromUri.indexOf("@"); + fromQString = fromUri.mid(left, right - left); + displayname = fromUri.left(fromUri.indexOf("<") - 1); + } + Q_EMIT incomingCallWithMedia(accountId, callId, fromQString, displayname, mediaList); +} + +void +CallbacksHandler::slotMediaChangeRequested(const QString& accountId, + const QString& callId, + const VectorMapStringString& mediaList) +{ + Q_EMIT mediaChangeRequested(accountId, callId, mediaList); +} + +void +CallbacksHandler::slotCallStateChanged(const QString& accountId, + const QString& callId, + const QString& state, + int code) +{ + Q_EMIT callStateChanged(accountId, callId, state, code); +} + +void +CallbacksHandler::slotMediaNegotiationStatus(const QString& callId, + const QString& event, + const VectorMapStringString& mediaList) +{ + Q_EMIT mediaNegotiationStatus(callId, event, mediaList); +} + +void +CallbacksHandler::slotAccountDetailsChanged(const QString& accountId, const MapStringString& details) +{ + Q_EMIT accountDetailsChanged(accountId, details); +} + +void +CallbacksHandler::slotVolatileAccountDetailsChanged(const QString& accountId, + const MapStringString& details) +{ + Q_EMIT volatileAccountDetailsChanged(accountId, details); +} + +void +CallbacksHandler::slotAccountsChanged() +{ + Q_EMIT accountsChanged(); +} + +void +CallbacksHandler::slotRegistrationStateChanged(const QString& accountId, + const QString& registration_state, + unsigned detail_code, + const QString& detail_str) +{ + (void) detail_code; + (void) detail_str; + Q_EMIT accountStatusChanged(accountId, lrc::api::account::to_status(registration_state)); +} + +void +CallbacksHandler::slotIncomingMessage(const QString& accountId, + const QString& callId, + const QString& from, + const MapStringString& interaction) +{ + QString from2; + if (from.contains("@ring.dht")) { + from2 = QString(from).replace("@ring.dht", ""); + } else { + auto left = from.indexOf(":") + 1; + auto right = from.indexOf("@"); + from2 = from.mid(left, right - left); + } + + for (auto& e : interaction.toStdMap()) { + if (e.first.contains("x-ring/ring.profile.vcard")) { + auto pieces0 = e.first.split(";"); + auto pieces1 = pieces0[1].split(","); + auto pieces2 = pieces1[1].split("="); + auto pieces3 = pieces1[2].split("="); + Q_EMIT incomingVCardChunk(accountId, + callId, + from2, + pieces2[1].toInt(), + pieces3[1].toInt(), + e.second); + } else if (e.first.contains( + "text/plain")) { // we consider it as an usual message interaction + Q_EMIT incomingCallMessage(accountId, callId, from2, e.second); + } + } +} + +void +CallbacksHandler::slotConferenceCreated(const QString& accountId, const QString& callId) +{ + Q_EMIT conferenceCreated(accountId, callId); +} + +void +CallbacksHandler::slotConferenceChanged(const QString& accountId, + const QString& callId, + const QString& state) +{ + slotCallStateChanged(accountId, callId, state, 0); +} + +void +CallbacksHandler::slotConferenceRemoved(const QString& accountId, const QString& callId) +{ + Q_EMIT conferenceRemoved(accountId, callId); +} + +void +CallbacksHandler::slotAccountMessageStatusChanged(const QString& accountId, + const QString& conversationId, + const QString& peer, + const QString& messageId, + int status) +{ + Q_EMIT accountMessageStatusChanged(accountId, conversationId, peer, messageId, status); +} + +void +CallbacksHandler::slotDataTransferEvent(const QString& accountId, + const QString& conversationId, + const QString&, + const QString& fileId, + uint codeStatus) +{ + auto event = DRing::DataTransferEventCode(codeStatus); + + api::datatransfer::Info info; + if (conversationId.isEmpty()) { + try { + parent.getAccountModel() + .getAccountInfo(accountId) + .dataTransferModel->transferInfo(accountId, fileId, info); + } catch (...) { + return; + } + } else { + info.uid = fileId; + info.status = convertDataTransferEvent(event); + info.conversationId = conversationId; + info.accountId = accountId; + qlonglong totalSize, progress; + QString path; + try { + parent.getAccountModel().getAccountInfo(accountId).dataTransferModel->fileTransferInfo( + accountId, conversationId, fileId, path, totalSize, progress); + } catch (...) { + return; + } + auto fi = QFileInfo(path); + if (fi.isSymLink()) { + path = fi.symLinkTarget(); + } + info.path = path; + info.totalSize = totalSize; + info.progress = progress; + } + + // WARNING: info.status could be INVALID in case of async signaling + // So listeners must only take account of fileId in such case. + // Is useful for "termination" status like unjoinable_peer. + + switch (event) { + case DRing::DataTransferEventCode::created: + Q_EMIT transferStatusCreated(fileId, info); + break; + case DRing::DataTransferEventCode::closed_by_host: + case DRing::DataTransferEventCode::closed_by_peer: + Q_EMIT transferStatusCanceled(fileId, info); + break; + case DRing::DataTransferEventCode::wait_peer_acceptance: + Q_EMIT transferStatusAwaitingPeer(fileId, info); + break; + case DRing::DataTransferEventCode::wait_host_acceptance: + Q_EMIT transferStatusAwaitingHost(fileId, info); + break; + case DRing::DataTransferEventCode::ongoing: + Q_EMIT transferStatusOngoing(fileId, info); + break; + case DRing::DataTransferEventCode::finished: + Q_EMIT transferStatusFinished(fileId, info); + break; + case DRing::DataTransferEventCode::invalid_pathname: + case DRing::DataTransferEventCode::unsupported: + Q_EMIT transferStatusError(fileId, info); + break; + case DRing::DataTransferEventCode::timeout_expired: + Q_EMIT transferStatusTimeoutExpired(fileId, info); + break; + case DRing::DataTransferEventCode::unjoinable_peer: + Q_EMIT transferStatusUnjoinable(fileId, info); + break; + case DRing::DataTransferEventCode::invalid: + break; + } +} + +void +CallbacksHandler::slotKnownDevicesChanged(const QString& accountId, const MapStringString& devices) +{ + Q_EMIT knownDevicesChanged(accountId, devices); +} + +void +CallbacksHandler::slotDeviceRevokationEnded(const QString& accountId, + const QString& deviceId, + const int status) +{ + Q_EMIT deviceRevocationEnded(accountId, deviceId, status); +} + +void +CallbacksHandler::slotAccountProfileReceived(const QString& accountId, + const QString& displayName, + const QString& userPhoto) +{ + Q_EMIT accountProfileReceived(accountId, displayName, userPhoto); +} + +void +CallbacksHandler::slotExportOnRingEnded(const QString& accountId, int status, const QString& pin) +{ + Q_EMIT exportOnRingEnded(accountId, status, pin); +} + +void +CallbacksHandler::slotNameRegistrationEnded(const QString& accountId, + int status, + const QString& name) +{ + Q_EMIT nameRegistrationEnded(accountId, status, name); +} + +void +CallbacksHandler::slotRegisteredNameFound(const QString& accountId, + int status, + const QString& address, + const QString& name) +{ + Q_EMIT registeredNameFound(accountId, status, address, name); +} + +void +CallbacksHandler::slotMigrationEnded(const QString& accountId, const QString& status) +{ + Q_EMIT migrationEnded(accountId, status == "SUCCESS"); +} + +void +CallbacksHandler::slotDebugMessageReceived(const QString& message) +{ + Q_EMIT parent.getBehaviorController().debugMessageReceived(message); +} + +void +CallbacksHandler::slotAudioDeviceEvent() +{ + Q_EMIT audioDeviceEvent(); +} + +void +CallbacksHandler::slotAudioMeterReceived(const QString& id, float level) +{ + Q_EMIT audioMeter(id, level); +} + +void +CallbacksHandler::slotRemoteRecordingChanged(const QString& callId, + const QString& peerNumber, + bool state) +{ + Q_EMIT remoteRecordingChanged(callId, peerNumber, state); +} + +void +CallbacksHandler::slotConversationLoaded(uint32_t requestId, + const QString& accountId, + const QString& conversationId, + const VectorMapStringString& messages) +{ + Q_EMIT conversationLoaded(requestId, accountId, conversationId, messages); +} + +void +CallbacksHandler::slotMessageReceived(const QString& accountId, + const QString& conversationId, + const MapStringString& message) +{ + Q_EMIT messageReceived(accountId, conversationId, message); +} + +void +CallbacksHandler::slotConversationRequestReceived(const QString& accountId, + const QString& conversationId, + const MapStringString& metadatas) +{ + Q_EMIT conversationRequestReceived(accountId, conversationId, metadatas); +} + +void +CallbacksHandler::slotConversationRequestDeclined(const QString& accountId, + const QString& conversationId) +{ + Q_EMIT conversationRequestDeclined(accountId, conversationId); +} + +void +CallbacksHandler::slotConversationReady(const QString& accountId, const QString& conversationId) +{ + Q_EMIT conversationReady(accountId, conversationId); +} + +void +CallbacksHandler::slotConversationRemoved(const QString& accountId, const QString& conversationId) +{ + Q_EMIT conversationRemoved(accountId, conversationId); +} + +void +CallbacksHandler::slotConversationMemberEvent(const QString& accountId, + const QString& conversationId, + const QString& memberId, + int event) +{ + Q_EMIT conversationMemberEvent(accountId, conversationId, memberId, event); +} + +} // namespace lrc diff --git a/src/libclient/callbackshandler.h b/src/libclient/callbackshandler.h new file mode 100644 index 0000000000000000000000000000000000000000..3417bf947c7d93f6a001138fe5b9382d2e7a3ccb --- /dev/null +++ b/src/libclient/callbackshandler.h @@ -0,0 +1,679 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#include "typedefs.h" +#include "api/datatransfer.h" +#include "qtwrapper/conversions_wrap.hpp" + +#include <QObject> + +#include <memory> + +namespace lrc { + +namespace api { +class Lrc; + +namespace account { +enum class Status; +} +} // namespace api + +class CallbacksHandler : public QObject +{ + Q_OBJECT + +public: + CallbacksHandler(const api::Lrc& parent); + ~CallbacksHandler(); + + // This connection relies on the behavior controller + // and needs to be made after the lrc object is constructed + void subscribeToDebugReceived(); + +Q_SIGNALS: + /** + * Connect this signal to get incoming text interaction from the DHT. + * @param accountId interaction receiver. + * @param msgId interaction's id. + * @param from interaction sender. + * @param payloads. + */ + void newAccountMessage(const QString& accountId, + const QString& from, + const QString& msgId, + const MapStringString& payloads); + /** + * Connect this signal to get information when a peer is online. + * @param accountId related account. + * @param contactUri the peer. + * @param present if the peer is online. + */ + void newBuddySubscription(const QString& accountId, const QString& contactUri, bool present); + /** + * Connect this signal to get information when peer discovery changes. + * @param contactUri the peer. + * @param state is 0 if the peer is added. + */ + void newPeerSubscription(const QString& accountId, + const QString& contactUri, + int state, + const QString& displayname); + /** + * Connect this signal to know when a contact is removed by the daemon. + * @param accountId the one who lost a contact. + * @param contactUri the contact removed. + * @param banned if the contact was banned + */ + void contactRemoved(const QString& accountId, const QString& contactUri, bool banned); + /** + * Connect this signal to know when a contact is added by the daemon. + * @param accountId the one who got a new contact. + * @param contactUri the new contact. + * @param confirmed if the contact is trusted. + */ + void contactAdded(const QString& accountId, const QString& contactUri, bool confirmed); + /** + * Connect this signal to know when an incoming request is added by the daemon + * @param accountId the one who got the request + * @param contactUri the peer contact + * @param payload the VCard + */ + void incomingContactRequest(const QString& accountId, + const QString& conversationId, + const QString& contactUri, + const QString& payload); + /** + * Connect this signal to know when a call arrives + * @param accountId the one who receives the call + * @param callId the call id + * @param fromUri the caller uri + * @param displayName the display name of incoming call + * @param mediaList media received + */ + void incomingCallWithMedia(const QString& accountId, + const QString& callId, + const QString& fromUri, + const QString& displayName, + const VectorMapStringString& mediaList); + /** + * Connect this signal to know when a call arrives + * @param accountId the one who receives the call + * @param callId the call id + * @param mediaList new media received + */ + void mediaChangeRequested(const QString& accountId, + const QString& callId, + const VectorMapStringString& mediaList); + /** + * Connect this signal to know when a call is updated + * @param accountId + * @param callId the call id + * @param state the new state + * @param code + */ + void callStateChanged(const QString& accountId, + const QString& callId, + const QString& state, + int code); + /** + * Connect this signal to know when a call medias are available + * @param callId the call id + * @param event + * @param mediaList new mediaList for the call + */ + void mediaNegotiationStatus(const QString& callId, + const QString& event, + const VectorMapStringString& mediaList); + /** + * Connect this signal to know when the account details have changed + * @param accountId the one who changes + * @param details the new details + */ + void accountDetailsChanged(const QString& accountId, const MapStringString& details); + /** + * Connect this signal to know when the volatile account details have changed + * @param accountId the one who changes + * @param details the new details + */ + void volatileAccountDetailsChanged(const QString& accountId, const MapStringString& details); + /** + * Connect this signal to know when the accounts list changed + */ + void accountsChanged(); + /** + * Connect this signal to know when the account status changed + * @param accountId the one who changes + * @param status the new status + */ + void accountStatusChanged(const QString& accountId, const api::account::Status status); + /** + * Connect this signal to know where a VCard is incoming + * @param accountId + * @param callId the call linked to this VCard + * @param from the sender URI + * @param part the number of the part + * @param numberOfParts of the VCard + * @param payload content of the VCard + */ + void incomingVCardChunk(const QString& accountId, + const QString& callId, + const QString& from, + int part, + int numberOfParts, + const QString& payload); + /** + * Connect this signal to get incoming text interaction from SIP. + * @param accountId the account linked. + * @param callId the call linked. + * @param from interaction sender. + * @param body the text received. + */ + void incomingCallMessage(const QString& accountId, + const QString& callId, + const QString& from, + const QString& body) const; + /** + * Connect this signal to know when a new conference is created + * @param callId of the conference + */ + void conferenceCreated(const QString& accountId, const QString& callId); + /** + * Connect this signal to know when a conference is removed + * @param accountId + * @param callId of the conference + */ + void conferenceRemoved(const QString& accountId, const QString& callId); + /** + * Connect this signal to know when a message sent get a new status + * @param accountId, account linked + * @param messageId id of the message + * @param conversationId id of the conversation + * @param peer, peer uri + * @param status, new status for this message + */ + void accountMessageStatusChanged(const QString& accountId, + const QString& conversationId, + const QString& peer, + const QString& messageId, + int status); + + void transferStatusCreated(const QString& fileId, api::datatransfer::Info info); + void transferStatusCanceled(const QString& fileId, api::datatransfer::Info info); + void transferStatusAwaitingPeer(const QString& fileId, api::datatransfer::Info info); + void transferStatusAwaitingHost(const QString& fileId, api::datatransfer::Info info); + void transferStatusOngoing(const QString& fileId, api::datatransfer::Info info); + void transferStatusFinished(const QString& fileId, api::datatransfer::Info info); + void transferStatusError(const QString& fileId, api::datatransfer::Info info); + void transferStatusTimeoutExpired(const QString& fileId, api::datatransfer::Info info); + void transferStatusUnjoinable(const QString& fileId, api::datatransfer::Info info); + + /** + * Connect this signal to get when a device name changed or a device is added + * @param accountId interaction receiver. + * @param devices A map of device IDs with corresponding labels. + */ + void knownDevicesChanged(const QString& accountId, const MapStringString& devices); + + /** + * Emit deviceRevocationEnded + * @param accountId + * @param deviceId + * @param status SUCCESS = 0, WRONG_PASSWORD = 1, UNKNOWN_DEVICE = 2 + */ + void deviceRevocationEnded(const QString& accountId, const QString& deviceId, const int status); + + /** + * Account profile has been received + * @param accountId + * @param displayName + * @param userPhoto + */ + void accountProfileReceived(const QString& accountId, + const QString& displayName, + const QString& userPhoto); + + /** + * Emit exportOnRingEnded + * @param accountId + * @param status SUCCESS = 0, WRONG_PASSWORD = 1, NETWORK_ERROR = 2 + * @param pin + */ + void exportOnRingEnded(const QString& accountId, int status, const QString& pin); + + /** + * Name registration has ended + * @param accountId + * @param status + * @param name + */ + void nameRegistrationEnded(const QString& accountId, int status, const QString& name); + + /** + * Name registration has been found + * @param accountId + * @param status + * @param name + */ + void registeredNameFound(const QString& accountId, + int status, + const QString& address, + const QString& name); + + /** + * Migration ended + * @param accountId + * @param ok if migration succeed + */ + void migrationEnded(const QString& accountId, bool ok); + + /** + * Debug message received + * @param message + */ + void debugMessageReceived(const QString& message); + + /** + * Renderer is started + * @param id + * @param shmrenderer + * @param width + * @param height + */ + void decodingStarted(const QString& id, const QString& shmPath, int width, int height); + + /** + * Renderer is stopped + * @param id + * @param shmrenderer + */ + void decodingStopped(const QString& id, const QString& shmPath); + + /** + * Emitted when a video device is plugged or unplugged + */ + void deviceEvent(); + + /** + * Emitted when an audio level is plugged or unplugged + */ + void audioDeviceEvent(); + + /** + * Emitted when an audio level is received + * @param id of the ringbuffer level + * @param level + */ + void audioMeter(const QString& id, float level); + + /** + * Emitted when an local recorder is finished + * @param filePath + */ + void recordPlaybackStopped(const QString& filePath); + + /** + * Emitted when an audio level is received + * @param accountId + * @param newCount + * @param oldCount + * @param urgentCount + */ + void voiceMailNotify(const QString& accountId, int newCount, int oldCount, int urgentCount); + + /** + * Connect this signal to know when a call is updated + * @param callId the call id + * @param callId the contact id + * @param state the new state + * @param code + */ + void remoteRecordingChanged(const QString& callId, const QString& peerNumber, bool state); + void conversationLoaded(uint32_t requestId, + const QString& accountId, + const QString& conversationId, + const VectorMapStringString& messages); + void messageReceived(const QString& accountId, + const QString& conversationId, + const MapStringString& message); + void conversationRequestReceived(const QString& accountId, + const QString& conversationId, + const MapStringString& metadatas); + void conversationRequestDeclined(const QString& accountId, const QString& conversationId); + void conversationReady(const QString& accountId, const QString& conversationId); + void conversationRemoved(const QString& accountId, const QString& conversationId); + void conversationMemberEvent(const QString& accountId, + const QString& conversationId, + const QString& memberId, + int event); + +private Q_SLOTS: + /** + * Emit newAccountMessage + * @param accountId + * @param peerId + * @param msgId + * @param payloads of the interaction + */ + void slotNewAccountMessage(const QString& accountId, + const QString& peerId, + const QString& msgId, + const QMap<QString, QString>& payloads); + /** + * Emit newBuddySubscription + * @param accountId + * @param contactUri + * @param status if the contact is present + * @param message unused for now + */ + void slotNewBuddySubscription(const QString& accountId, + const QString& contactUri, + bool status, + const QString& message); + /** + * Emit contactAdded + * @param accountId account linked + * @param contactUri + * @param confirmed + */ + void slotContactAdded(const QString& accountId, const QString& contactUri, bool confirmed); + /** + * Emit contactRemoved + * @param accountId account linked + * @param contactUri + * @param banned + */ + void slotContactRemoved(const QString& accountId, const QString& contactUri, bool banned); + /** + * Emit incomingContactRequest + * @param accountId the linked id + * @param ringId the peer contact + * @param payload the VCard + * @param time when the request was received + */ + void slotIncomingContactRequest(const QString& accountId, + const QString& conversationId, + const QString& ringId, + const QByteArray& payload, + time_t time); + /** + * Emit accountDetailsChanged + * @param accountId + * @param details + */ + void slotAccountDetailsChanged(const QString& accountId, const MapStringString& details); + /** + * Emit volatileAccountDetailsChanged + * @param accountId + * @param details + */ + void slotVolatileAccountDetailsChanged(const QString& accountId, const MapStringString& details); + /** + * Emit accountsChanged + */ + void slotAccountsChanged(); + + /** + * Emit accountStatusChanged + * @param accountId + * @param registration_state + * @param detail_code + * @param detail_str + */ + void slotRegistrationStateChanged(const QString& accountId, + const QString& registration_state, + unsigned detail_code, + const QString& detail_str); + /** + * @deprecated Use slotIncomingCallWithMedia instead + * Get the URI of the peer and emit incomingCall + * @param accountId account linked + * @param callId the incoming call id + * @param fromUri the uri of the peer + */ + void slotIncomingCall(const QString& accountId, const QString& callId, const QString& fromUri); + /** + * Get the URI of the peer and emit incomingCallWithMedia + * @param accountId account linked + * @param callId the incoming call id + * @param fromUri the uri of the peer + * @param mediaList the mediaList received + */ + void slotIncomingCallWithMedia(const QString& accountId, + const QString& callId, + const QString& fromUri, + const VectorMapStringString& mediaList); + /** + * Get the URI of the peer and emit mediaChangeRequested + * @param accountId account linked + * @param callId the incoming call id + * @param mediaList the mediaList received + */ + void slotMediaChangeRequested(const QString& accountId, + const QString& callId, + const VectorMapStringString& mediaList); + /** + * Emit callStateChanged + * @param accountId + * @param callId the call which changes. + * @param state the new state + * @param code unused for now + */ + void slotCallStateChanged(const QString& accountId, + const QString& callId, + const QString& state, + int code); + /** + * Emit mediaNegotiationStatus + * @param callId the call which changes. + * @param eventstate the new state + * @param mediaList new mediaList for the call + */ + void slotMediaNegotiationStatus(const QString& callId, + const QString& event, + const VectorMapStringString& mediaList); + /** + * Parse a call message and emit incomingVCardChunk if it's a VCard chunk + * else incomingCallMessage if it's a text message + * @param accountId account linked + * @param callId call linked + * @param from the URI + * @param interaction the content of the Message. + */ + void slotIncomingMessage(const QString& accountId, + const QString& callId, + const QString& from, + const QMap<QString, QString>& interaction); + /** + * Emit conferenceCreated + * @param accountId + * @param callId of the conference + */ + void slotConferenceCreated(const QString& accountId, const QString& callId); + /** + * Emit conferenceRemove + * @param accountId + * @param callId of the conference + */ + void slotConferenceRemoved(const QString& accountId, const QString& callId); + /** + * Call slotCallStateChanged + * @param accountId + * @param callId of the conference + * @param state, new state + */ + void slotConferenceChanged(const QString& accountId, + const QString& callId, + const QString& state); + /** + * Emit accountMessageStatusChanged + * @param accountId, account linked + * @param messageId id of the message + * @param conversationId id of the conversation + * @param peer, peer uri + * @param status, new status for this message + */ + void slotAccountMessageStatusChanged(const QString& accountId, + const QString& conversationId, + const QString& peer, + const QString& messageId, + int status); + + void slotDataTransferEvent(const QString& accountId, + const QString& conversationId, + const QString& interactionId, + const QString& fileId, + uint code); + + /** + * Emit knownDevicesChanged + * @param accountId + * @param devices A map of device IDs and corresponding labels + */ + void slotKnownDevicesChanged(const QString& accountId, const MapStringString& devices); + + /** + * Emit deviceRevocationEnded + * @param accountId + * @param deviceId + * @param status SUCCESS = 0, WRONG_PASSWORD = 1, UNKNOWN_DEVICE = 2 + */ + void slotDeviceRevokationEnded(const QString& accountId, + const QString& deviceId, + const int status); + + /** + * Emit account avatar has been received + * @param accountId + * @param displayName + * @param userPhoto + */ + void slotAccountProfileReceived(const QString& accountId, + const QString& displayName, + const QString& userPhoto); + + /** + * Emit exportOnRingEnded + * @param accountId + * @param status SUCCESS = 0, WRONG_PASSWORD = 1, NETWORK_ERROR = 2 + * @param pin + */ + void slotExportOnRingEnded(const QString& accountId, int status, const QString& pin); + + /** + * Emit nameRegistrationEnded + * @param accountId + * @param status + * @param name + */ + void slotNameRegistrationEnded(const QString& accountId, int status, const QString& name); + + /** + * Emit registeredNameFound + * @param accountId + * @param status + * @param name + */ + void slotRegisteredNameFound(const QString& accountId, + int status, + const QString& address, + const QString& name); + + /** + * emit migrationEnded + * @param accountId + * @param status + */ + void slotMigrationEnded(const QString& accountId, const QString& status); + + /** + * emit debugMessageReceived + * @param message + */ + void slotDebugMessageReceived(const QString& message); + + /** + * Detect when an audio device is plugged or unplugged + */ + void slotAudioDeviceEvent(); + + /** + * Called when an audio meter level is received + * @param id of the ringbuffer level + * @param level + */ + void slotAudioMeterReceived(const QString& id, float level); + + /** + * Emit newPeerSubscription + * @param accountId + * @param contactUri + * @param status if the peer is added or removed + * @param displayname is the account display name + */ + void slotNearbyPeerSubscription(const QString& accountId, + const QString& contactUri, + int state, + const QString& displayname); + + /** + * Emit voiceMailNotify + * @param accountId + * @param new VM + * @param old VM + * @param new Urgent VM + */ + void slotVoiceMailNotify(const QString& accountId, int newCount, int oldCount, int urgentCount); + + /** + * Emit recordPlaybackStopped + * @param filePath + */ + void slotRecordPlaybackStopped(const QString& filePath); + + /** + * Call slotCallStateChanged + * @param callId of the conference + * @param state, new state + */ + void slotRemoteRecordingChanged(const QString& callId, const QString& contactId, bool state); + void slotConversationLoaded(uint32_t requestId, + const QString& accountId, + const QString& conversationId, + const VectorMapStringString& messages); + void slotMessageReceived(const QString& accountId, + const QString& conversationId, + const MapStringString& message); + void slotConversationRequestReceived(const QString& accountId, + const QString& conversationId, + const MapStringString& metadatas); + void slotConversationRequestDeclined(const QString& accountId, const QString& conversationId); + void slotConversationReady(const QString& accountId, const QString& conversationId); + void slotConversationRemoved(const QString& accountId, const QString& conversationId); + void slotConversationMemberEvent(const QString& accountId, + const QString& conversationId, + const QString& memberId, + int event); + +private: + const api::Lrc& parent; +}; + +} // namespace lrc diff --git a/src/libclient/callparticipantsmodel.cpp b/src/libclient/callparticipantsmodel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..691d28597595885400fc7145f41d7410952750c3 --- /dev/null +++ b/src/libclient/callparticipantsmodel.cpp @@ -0,0 +1,205 @@ +/*! + * Copyright (C) 2022 Savoir-faire Linux Inc. + * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "api/callparticipantsmodel.h" + +#include "api/account.h" +#include "api/contactmodel.h" +#include "api/contact.h" +#include "api/newcallmodel.h" +#include "api/newaccountmodel.h" + +namespace lrc { + +namespace api { + +CallParticipants::CallParticipants(const VectorMapStringString& infos, + const QString& callId, + const NewCallModel& linked) + : linked_(linked) + , callId_(callId) +{ + update(infos); +} + +QList<ParticipantInfos> +CallParticipants::getParticipants() const +{ + std::lock_guard<std::mutex> lk(participantsMtx_); + return participants_.values(); +} + +void +CallParticipants::update(const VectorMapStringString& infos) +{ + std::lock_guard<std::mutex> lk(updateMtx_); + validUris_.clear(); + filterCandidates(infos); + validUris_.sort(); + + idx_ = 0; + QList<QString> keys {}; + { + std::lock_guard<std::mutex> lk(participantsMtx_); + keys = participants_.keys(); + } + for (const auto& key : keys) { + auto keyIdx = validUris_.indexOf(key); + if (keyIdx < 0 || keyIdx >= validUris_.size()) + removeParticipant(idx_); + else + idx_++; + } + + idx_ = 0; + for (const auto& partUri : validUris_) { + addParticipant(candidates_[partUri]); + idx_++; + } + + verifyLayout(); +} + +void +CallParticipants::verifyLayout() +{ + std::lock_guard<std::mutex> lk(participantsMtx_); + auto it = std::find_if(participants_.begin(), + participants_.end(), + [](const lrc::api::ParticipantInfos& participant) -> bool { + return participant.active; + }); + + auto newLayout = call::Layout::GRID; + if (it != participants_.end()) + if (participants_.size() == 1) + newLayout = call::Layout::ONE; + else + newLayout = call::Layout::ONE_WITH_SMALL; + else + newLayout = call::Layout::GRID; + + if (newLayout != hostLayout_) + hostLayout_ = newLayout; +} + +void +CallParticipants::removeParticipant(int index) +{ + { + std::lock_guard<std::mutex> lk(participantsMtx_); + auto it = participants_.begin() + index; + participants_.erase(it); + } + Q_EMIT linked_.participantRemoved(callId_, idx_); +} + +void +CallParticipants::addParticipant(const ParticipantInfos& participant) +{ + bool added {false}; + { + std::lock_guard<std::mutex> lk(participantsMtx_); + auto it = participants_.find(participant.uri); + if (it == participants_.end()) { + participants_.insert(participants_.begin() + idx_, participant.uri, participant); + added = true; + } else { + if (participant == (*it)) + return; + (*it) = participant; + } + } + if (added) + Q_EMIT linked_.participantAdded(callId_, idx_); + else + Q_EMIT linked_.participantUpdated(callId_, idx_); +} + +void +CallParticipants::filterCandidates(const VectorMapStringString& infos) +{ + std::lock_guard<std::mutex> lk(participantsMtx_); + candidates_.clear(); + for (const auto& candidate : infos) { + auto peerId = candidate[ParticipantsInfosStrings::URI]; + peerId.truncate(peerId.lastIndexOf("@")); + if (peerId.isEmpty()) { + for (const auto& accId : linked_.owner.accountModel->getAccountList()) { + try { + auto& accountInfo = linked_.owner.accountModel->getAccountInfo(accId); + if (accountInfo.callModel->hasCall(callId_)) { + peerId = accountInfo.profileInfo.uri; + } + } catch (...) { + } + } + } + if (candidate[ParticipantsInfosStrings::W].toInt() != 0 + && candidate[ParticipantsInfosStrings::H].toInt() != 0) { + validUris_.append(peerId); + candidates_.insert(peerId, ParticipantInfos(candidate, callId_, peerId)); + } + } +} + +bool +CallParticipants::checkModerator(const QString& uri) const +{ + std::lock_guard<std::mutex> lk(participantsMtx_); + return std::find_if(participants_.cbegin(), + participants_.cend(), + [&](auto participant) { + return participant.uri == uri && participant.isModerator; + }) + != participants_.cend(); +} + +QJsonObject +CallParticipants::toQJsonObject(uint index) const +{ + std::lock_guard<std::mutex> lk(participantsMtx_); + if (index >= participants_.size()) + return {}; + + QJsonObject ret; + const auto& participant = participants_.begin() + index; + + ret[ParticipantsInfosStrings::URI] = participant->uri; + ret[ParticipantsInfosStrings::DEVICE] = participant->device; + ret[ParticipantsInfosStrings::SINKID] = participant->sinkId; + ret[ParticipantsInfosStrings::BESTNAME] = participant->bestName; + ret[ParticipantsInfosStrings::AVATAR] = participant->avatar; + ret[ParticipantsInfosStrings::ACTIVE] = participant->active; + ret[ParticipantsInfosStrings::X] = participant->x; + ret[ParticipantsInfosStrings::Y] = participant->y; + ret[ParticipantsInfosStrings::WIDTH] = participant->width; + ret[ParticipantsInfosStrings::HEIGHT] = participant->height; + ret[ParticipantsInfosStrings::AUDIOLOCALMUTED] = participant->audioLocalMuted; + ret[ParticipantsInfosStrings::AUDIOMODERATORMUTED] = participant->audioModeratorMuted; + ret[ParticipantsInfosStrings::VIDEOMUTED] = participant->videoMuted; + ret[ParticipantsInfosStrings::ISMODERATOR] = participant->isModerator; + ret[ParticipantsInfosStrings::ISLOCAL] = participant->islocal; + ret[ParticipantsInfosStrings::ISCONTACT] = participant->isContact; + ret[ParticipantsInfosStrings::HANDRAISED] = participant->handRaised; + ret[ParticipantsInfosStrings::CALLID] = callId_; + + return ret; +} +} // end namespace api +} // end namespace lrc diff --git a/src/libclient/chatview.cpp b/src/libclient/chatview.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ae9d02a37ca526e3e401a2e9f10a6df7b23b887c --- /dev/null +++ b/src/libclient/chatview.cpp @@ -0,0 +1,85 @@ +/**************************************************************************** + * Copyright (C) 2020-2022 Savoir-faire Linux Inc. * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#include "api/chatview.h" + +namespace lrc { + +namespace api { + +namespace chatview { + +QVariantMap +getTranslatedStrings(bool qwebview) +{ + return { + {"Hide chat view", QObject::tr("Hide chat view")}, + {"Place video call", QObject::tr("Place video call")}, + {"Show available plugins", QObject::tr("Show available plugins")}, + {"Place audio call", QObject::tr("Place audio call")}, + {"Add to conversations", QObject::tr("Add to conversations")}, + {"Unban contact", QObject::tr("Unban contact")}, + {"Send", QObject::tr("Send")}, + {"Options", QObject::tr("Options")}, + {"Jump to latest", QObject::tr("Jump to latest")}, + {"Send file", QObject::tr("Send file")}, + {"Add emoji", QObject::tr("Add emoji")}, + {"Leave video message", QObject::tr("Leave video message")}, + {"Leave audio message", QObject::tr("Leave audio message")}, + {"Block", QObject::tr("Block")}, + {"Copy to downloads", QObject::tr("Copy to downloads")}, + {"Write to {0}", QObject::tr("Write to {0}")}, + {"Note: an interaction will create a new contact.", + QObject::tr("Note: an interaction will create a new contact.")}, + {"is not in your contacts", QObject::tr("is not in your contacts")}, + {"has sent you a conversation request.", + QObject::tr("has sent you a conversation request.")}, + {"Hello, do you want to join the conversation?", + QObject::tr("Hello, do you want to join the conversation?")}, + {"You have accepted the conversation request.", + QObject::tr("You have accepted the conversation request.")}, + {"We are waiting for another device to synchronize the conversation.", + QObject::tr("We are waiting for another device to synchronize the conversation.")}, + {"Note: you can automatically accept this invitation by sending a message.", + QObject::tr("Note: you can automatically accept this invitation by sending a message.")}, + {"%d days ago", qwebview ? QObject::tr("{0} days ago") : QObject::tr("%d days ago")}, + {"%d hours ago", qwebview ? QObject::tr("{0} hours ago") : QObject::tr("%d hours ago")}, + {"%d minutes ago", + qwebview ? QObject::tr("{0} minutes ago") : QObject::tr("%d minutes ago")}, + {"one day ago", QObject::tr("one day ago")}, + {"one hour ago", QObject::tr("one hour ago")}, + {"just now", QObject::tr("just now")}, + {"Failure", QObject::tr("Failure")}, + {"Accept", QObject::tr("Accept")}, + {"Refuse", QObject::tr("Refuse")}, + {"Delete", QObject::tr("Delete")}, + {"Retry", QObject::tr("Retry")}, + {"unjoinable peer", QObject::tr("Unable to make contact")}, + {"connecting", QObject::tr("Connecting")}, + {"accepted", QObject::tr("Accepted")}, + {"canceled", QObject::tr("Canceled")}, + {"ongoing", QObject::tr("Ongoing")}, + {"awaiting peer", QObject::tr("Waiting for contact")}, + {"awaiting host", QObject::tr("Incoming transfer")}, + {"awaiting peer timeout", QObject::tr("Timed out waiting for contact")}, + {"finished", QObject::tr("Finished")}, + }; +} + +} // namespace chatview +} // namespace api +} // namespace lrc diff --git a/src/libclient/contactmodel.cpp b/src/libclient/contactmodel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..63e4825db36d951177f5fd57f3e05f7cd4df4385 --- /dev/null +++ b/src/libclient/contactmodel.cpp @@ -0,0 +1,1303 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com> * + * Author: Hugo Lefeuvre <hugo.lefeuvre@savoirfairelinux.com> * + * Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com> * + * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include "api/contactmodel.h" + +// LRC +#include "api/account.h" +#include "api/contact.h" +#include "api/conversationmodel.h" +#include "api/interaction.h" +#include "api/lrc.h" +#include "api/newaccountmodel.h" +#include "api/newcallmodel.h" +#include "callbackshandler.h" +#include "uri.h" +#include "vcard.h" +#include "typedefs.h" + +#include "authority/daemon.h" +#include "authority/storagehelper.h" + +// Dbus +#include "dbus/configurationmanager.h" +#include "dbus/presencemanager.h" + +#include "account_const.h" + +// Std +#include <algorithm> +#include <mutex> + +namespace lrc { + +using namespace api; + +class ContactModelPimpl : public QObject +{ + Q_OBJECT +public: + ContactModelPimpl(const ContactModel& linked, + Database& db, + const CallbacksHandler& callbacksHandler, + const BehaviorController& behaviorController); + + ~ContactModelPimpl(); + + /** + * Fills the contacts based on database's conversations + * @return if the method succeeds + */ + bool fillWithSIPContacts(); + + /** + * Fills the contacts based on database's conversations + * @return if the method succeeds + */ + bool fillWithJamiContacts(); + + /** + * Add a contact::Info to contacts. + * @note: the contactId must corresponds to a profile in the database. + * @param contactId + * @param type + * @param displayName + * @param banned whether contact is banned or not + * @param conversationId linked swarm if one + */ + void addToContacts(const QString& contactId, + const profile::Type& type, + const QString& displayName = "", + bool banned = false, + const QString& conversationId = ""); + /** + * Helpers for searchContact. Search for a given classic or SIP contact. + */ + void searchContact(const URI& query); + void searchSipContact(const URI& query); + + /** + * Update temporary item to display a given message about a given uri. + */ + void updateTemporaryMessage(const QString& mes); + + /** + * Check if equivalent uri exist in contact + */ + QString sipUriReceivedFilter(const QString& uri); + + // Helpers + const BehaviorController& behaviorController; + const ContactModel& linked; + Database& db; + const CallbacksHandler& callbacksHandler; + + // Containers + ContactModel::ContactInfoMap contacts; + ContactModel::ContactInfoMap searchResult; + QList<QString> bannedContacts; + QString searchQuery; + std::mutex contactsMtx_; + std::mutex bannedContactsMtx_; + QString searchStatus_ {}; + +public Q_SLOTS: + /** + * Listen CallbacksHandler when a presence update occurs + * @param accountId + * @param contactUri + * @param status + */ + void slotNewBuddySubscription(const QString& accountId, const QString& uri, bool status); + + /** + * Listen CallbacksHandler when a contact is added + * @param accountId + * @param contactUri + * @param confirmed + */ + void slotContactAdded(const QString& accountId, const QString& contactUri, bool confirmed); + + /** + * Listen CallbacksHandler when a contact is removed + * @param accountId + * @param contactUri + * @param banned + */ + void slotContactRemoved(const QString& accountId, const QString& contactUri, bool banned); + + /** + * Listen CallbacksHandler when a registeredName is found + * @param accountId account linked + * @param status (0 = SUCCESS, 1 = Not found, 2 = Network error) + * @param uri of the contact found + * @param registeredName of the contact found + */ + void slotRegisteredNameFound(const QString& accountId, + int status, + const QString& uri, + const QString& registeredName); + + /** + * Listen CallbacksHandler when an incoming request arrives + * @param accountId account linked + * @param contactUri + * @param payload VCard of the contact + */ + void slotIncomingContactRequest(const QString& accountId, + const QString& conversationId, + const QString& contactUri, + const QString& payload); + /** + * Listen from callModel when an incoming call arrives. + * @param fromId + * @param callId + * @param displayName + */ + void slotIncomingCall(const QString& fromId, const QString& callId, const QString& displayname); + + /** + * Listen from callbacksHandler for new account interaction and add pending contact if not present + * @param accountId + * @param msgId + * @param peerId + * @param payloads + */ + void slotNewAccountMessage(const QString& accountId, + const QString& peerId, + const QString& msgId, + const MapStringString& payloads); + + /** + * Listen from callbacksHandler to know when a file transfer interaction is incoming + * @param fileId Daemon's ID for incoming transfer + * @param transferInfo DataTransferInfo structure from daemon + */ + void slotNewAccountTransfer(const QString& fileId, datatransfer::Info info); + + /** + * Listen from daemon to know when a VCard is received + * @param accountId + * @param peer + * @param vCard + */ + void slotProfileReceived(const QString& accountId, const QString& peer, const QString& vCard); + + /** + * Listen from daemon to know when a user search completed + * @param accountId + * @param status + * @param query + * @param result + */ + void slotUserSearchEnded(const QString& accountId, + int status, + const QString& query, + const VectorMapStringString& result); +}; + +using namespace authority; + +ContactModel::ContactModel(const account::Info& owner, + Database& db, + const CallbacksHandler& callbacksHandler, + const BehaviorController& behaviorController) + : owner(owner) + , pimpl_(std::make_unique<ContactModelPimpl>(*this, db, callbacksHandler, behaviorController)) +{} + +ContactModel::~ContactModel() {} + +const ContactModel::ContactInfoMap& +ContactModel::getAllContacts() const +{ + return pimpl_->contacts; +} + +time_t +ContactModel::getAddedTs(const QString& contactUri) const +{ + MapStringString details = ConfigurationManager::instance().getContactDetails(owner.id, + contactUri); + auto itAdded = details.find("added"); + if (itAdded == details.end()) + return 0; + return itAdded.value().toUInt(); +} + +void +ContactModel::addContact(contact::Info contactInfo) +{ + auto& profile = contactInfo.profileInfo; + + // If passed contact is a banned contact, call the daemon to unban it + auto it = std::find(pimpl_->bannedContacts.begin(), pimpl_->bannedContacts.end(), profile.uri); + if (it != pimpl_->bannedContacts.end()) { + qDebug() << QString("Unban-ing contact %1").arg(profile.uri); + ConfigurationManager::instance().addContact(owner.id, profile.uri); + // bannedContacts will be updated in slotContactAdded + return; + } + + if ((owner.profileInfo.type != profile.type) + and (profile.type == profile::Type::JAMI or profile.type == profile::Type::SIP)) { + qDebug() << "ContactModel::addContact, types invalid."; + return; + } + + MapStringString details = ConfigurationManager::instance() + .getContactDetails(owner.id, contactInfo.profileInfo.uri); + + // if contactInfo is already a contact for the daemon, type should be equals to RING + // if the user add a temporary item for a SIP account, should be directly transformed + if (!details.empty() + || (profile.type == profile::Type::TEMPORARY + && owner.profileInfo.type == profile::Type::SIP)) + profile.type = owner.profileInfo.type; + + switch (profile.type) { + case profile::Type::TEMPORARY: { + // make a temporary contact available for UI elements, it will be upgraded to + // its corresponding type after receiving contact added signal + std::lock_guard<std::mutex> lk(pimpl_->contactsMtx_); + contactInfo.profileInfo.type = profile::Type::PENDING; + pimpl_->contacts.insert(contactInfo.profileInfo.uri, contactInfo); + ConfigurationManager::instance().addContact(owner.id, profile.uri); + ConfigurationManager::instance() + .sendTrustRequest(owner.id, + profile.uri, + owner.accountModel->accountVCard(owner.id).toUtf8()); + return; + } + case profile::Type::PENDING: + if (daemon::addContactFromPending(owner, profile.uri)) { + Q_EMIT pendingContactAccepted(profile.uri); + } else { + return; + } + break; + case profile::Type::JAMI: + case profile::Type::SIP: + break; + case profile::Type::INVALID: + case profile::Type::COUNT__: + default: + qDebug() << "ContactModel::addContact, cannot add contact with invalid type."; + return; + } + + storage::createOrUpdateProfile(owner.id, profile, true); + + { + std::lock_guard<std::mutex> lk(pimpl_->contactsMtx_); + auto iter = pimpl_->contacts.find(contactInfo.profileInfo.uri); + if (iter == pimpl_->contacts.end()) + pimpl_->contacts.insert(iter, contactInfo.profileInfo.uri, contactInfo); + else { + // On non-DBus platform, contactInfo.profileInfo.type may be wrong as the contact + // may be trusted already. We must use Profile::Type from pimpl_->contacts + // and not from contactInfo so we cannot revert a contact back to PENDING. + contactInfo.profileInfo.type = iter->profileInfo.type; + iter->profileInfo = contactInfo.profileInfo; + } + } + Q_EMIT profileUpdated(profile.uri); + if (profile.type == profile::Type::SIP) + Q_EMIT contactAdded(profile.uri); +} + +void +ContactModel::addToContacts(const QString& contactUri) +{ + std::lock_guard<std::mutex> lk(pimpl_->contactsMtx_); + auto iter = pimpl_->contacts.find(contactUri); + if (iter != pimpl_->contacts.end()) + return; + + auto contactInfo = storage::buildContactFromProfile(owner.id, + contactUri, + profile::Type::PENDING); + pimpl_->contacts.insert(iter, contactUri, contactInfo); + ConfigurationManager::instance().lookupAddress(owner.id, "", contactUri); +} + +void +ContactModel::removeContact(const QString& contactUri, bool banned) +{ + bool emitContactRemoved = false; + { + std::lock_guard<std::mutex> lk(pimpl_->contactsMtx_); + auto contact = pimpl_->contacts.find(contactUri); + if (!banned && contact != pimpl_->contacts.end() + && contact->profileInfo.type == profile::Type::PENDING) { + // Discard the pending request and remove profile from db if necessary + if (!daemon::discardFromPending(owner, contactUri)) { + qDebug() << "Discard request for account " << owner.id << " failed (" << contactUri + << ")"; + return; + } + pimpl_->contacts.remove(contactUri); + storage::removeContactConversations(pimpl_->db, contactUri); + storage::removeProfile(owner.id, contactUri); + emitContactRemoved = true; + } else if (owner.profileInfo.type == profile::Type::SIP) { + // Remove contact from db + pimpl_->contacts.remove(contactUri); + storage::removeContactConversations(pimpl_->db, contactUri); + storage::removeProfile(owner.id, contactUri); + emitContactRemoved = true; + } + } + // hang up calls with the removed contact as peer + try { + auto callinfo = owner.callModel->getCallFromURI(contactUri, true); + owner.callModel->hangUp(callinfo.id); + } catch (std::out_of_range& e) { + } + if (emitContactRemoved) { + Q_EMIT contactRemoved(contactUri); + } else { + // NOTE: this method is asynchronous, the model will be updated + // in slotContactRemoved + daemon::removeContact(owner, contactUri, banned); + } +} + +const contact::Info +ContactModel::getContact(const QString& contactUri) const +{ + std::lock_guard<std::mutex> lk(pimpl_->contactsMtx_); + if (pimpl_->contacts.contains(contactUri)) { + return pimpl_->contacts.value(contactUri); + } else if (pimpl_->searchResult.contains(contactUri)) { + return pimpl_->searchResult.value(contactUri); + } + throw std::out_of_range("Contact out of range"); +} + +const QList<QString>& +ContactModel::getBannedContacts() const +{ + return pimpl_->bannedContacts; +} + +ContactModel::ContactInfoMap +ContactModel::getSearchResults() const +{ + return pimpl_->searchResult; +} + +void +ContactModel::searchContact(const QString& query) +{ + // always reset temporary contact + pimpl_->searchResult.clear(); + + auto uri = URI(query); + QString uriID = uri.format(URI::Section::USER_INFO | URI::Section::HOSTNAME + | URI::Section::PORT); + pimpl_->searchQuery = uriID; + + auto uriScheme = uri.schemeType(); + if (static_cast<int>(uriScheme) > 2 && owner.profileInfo.type == profile::Type::SIP) { + // sip account do not care if schemeType is NONE, or UNRECOGNIZED (enum value > 2) + uriScheme = URI::SchemeType::SIP; + } else if (uriScheme == URI::SchemeType::NONE && owner.profileInfo.type == profile::Type::JAMI) { + uriScheme = URI::SchemeType::RING; + } + + if ((uriScheme == URI::SchemeType::SIP || uriScheme == URI::SchemeType::SIPS) + && owner.profileInfo.type == profile::Type::SIP) { + pimpl_->searchSipContact(uri); + } else if (uriScheme == URI::SchemeType::RING && owner.profileInfo.type == profile::Type::JAMI) { + pimpl_->searchContact(uri); + } else { + pimpl_->updateTemporaryMessage(tr("Bad URI scheme")); + } +} + +void +ContactModelPimpl::updateTemporaryMessage(const QString& mes) +{ + if (searchStatus_ != mes) { + searchStatus_ = mes; + linked.owner.conversationModel->updateSearchStatus(mes); + } +} + +void +ContactModelPimpl::searchContact(const URI& query) +{ + QString uriID = query.format(URI::Section::USER_INFO | URI::Section::HOSTNAME + | URI::Section::PORT); + if (query.isEmpty()) { + // This will remove the temporary item + Q_EMIT linked.modelUpdated(uriID); + updateTemporaryMessage(""); + return; + } + + if (query.protocolHint() == URI::ProtocolHint::RING) { + updateTemporaryMessage(""); + // no lookup, this is a ring infoHash + for (auto& i : contacts) { + if (i.profileInfo.uri == uriID) { + return; + } + } + auto& temporaryContact = searchResult[uriID]; + temporaryContact.profileInfo.uri = uriID; + temporaryContact.profileInfo.alias = uriID; + temporaryContact.profileInfo.type = profile::Type::TEMPORARY; + Q_EMIT linked.modelUpdated(uriID); + } else { + updateTemporaryMessage(tr("Searching…")); + + // If the username contains an @ it's an exact match + bool isJamsAccount = !linked.owner.confProperties.managerUri.isEmpty(); + if (isJamsAccount and not query.hasHostname()) + ConfigurationManager::instance().searchUser(linked.owner.id, uriID); + else + ConfigurationManager::instance().lookupName(linked.owner.id, "", uriID); + } +} + +void +ContactModelPimpl::searchSipContact(const URI& query) +{ + QString uriID = query.format(URI::Section::USER_INFO | URI::Section::HOSTNAME + | URI::Section::PORT); + if (query.isEmpty()) { + // This will remove the temporary item + Q_EMIT linked.modelUpdated(uriID); + updateTemporaryMessage(""); + return; + } + + { + std::lock_guard<std::mutex> lk(contactsMtx_); + if (contacts.find(uriID) == contacts.end()) { + auto& temporaryContact = searchResult[query]; + + temporaryContact.profileInfo.uri = uriID; + temporaryContact.profileInfo.alias = uriID; + temporaryContact.profileInfo.type = profile::Type::TEMPORARY; + } + } + Q_EMIT linked.modelUpdated(uriID); +} + +uint64_t +ContactModel::sendDhtMessage(const QString& contactUri, const QString& body) const +{ + // Send interaction + QMap<QString, QString> payloads; + payloads["text/plain"] = body; + auto msgId = ConfigurationManager::instance().sendTextMessage(QString(owner.id), + QString(contactUri), + payloads); + // NOTE: ConversationModel should store the interaction into the database + return msgId; +} + +const QString +ContactModel::bestNameForContact(const QString& contactUri) const +{ + try { + auto contact = getContact(contactUri); + auto alias = contact.profileInfo.alias.simplified(); + if (alias.isEmpty()) { + return bestIdFromContactInfo(contact); + } + return alias; + } catch (const std::out_of_range&) { + } + return contactUri; +} + +QString +ContactModel::avatar(const QString& uri) const +{ + { + std::lock_guard<std::mutex> lk(pimpl_->contactsMtx_); + // For search results it's loaded and not in storage yet. + if (pimpl_->searchResult.contains(uri)) { + auto contact = pimpl_->searchResult.value(uri); + return contact.profileInfo.avatar; + } + } + // Else search in storage + return storage::avatar(owner.id, uri); +} + +const QString +ContactModel::bestIdForContact(const QString& contactUri) const +{ + std::lock_guard<std::mutex> lk(pimpl_->contactsMtx_); + if (pimpl_->contacts.contains(contactUri)) { + auto contact = pimpl_->contacts.value(contactUri); + return bestIdFromContactInfo(contact); + } + return contactUri; +} + +const QString +ContactModel::bestIdFromContactInfo(const contact::Info& contactInfo) const +{ + auto registeredName = contactInfo.registeredName.simplified(); + auto infoHash = contactInfo.profileInfo.uri.simplified(); + + if (!registeredName.isEmpty()) { + return registeredName; + } + return infoHash; +} + +ContactModelPimpl::ContactModelPimpl(const ContactModel& linked, + Database& db, + const CallbacksHandler& callbacksHandler, + const BehaviorController& behaviorController) + : linked(linked) + , db(db) + , behaviorController(behaviorController) + , callbacksHandler(callbacksHandler) +{ + // Init contacts map + if (linked.owner.profileInfo.type == profile::Type::SIP) + fillWithSIPContacts(); + else + fillWithJamiContacts(); + + // connect the signals + connect(&callbacksHandler, + &CallbacksHandler::newBuddySubscription, + this, + &ContactModelPimpl::slotNewBuddySubscription); + connect(&callbacksHandler, + &CallbacksHandler::contactAdded, + this, + &ContactModelPimpl::slotContactAdded); + connect(&callbacksHandler, + &CallbacksHandler::contactRemoved, + this, + &ContactModelPimpl::slotContactRemoved); + connect(&callbacksHandler, + &CallbacksHandler::incomingContactRequest, + this, + &ContactModelPimpl::slotIncomingContactRequest); + connect(&callbacksHandler, + &CallbacksHandler::registeredNameFound, + this, + &ContactModelPimpl::slotRegisteredNameFound); + connect(&*linked.owner.callModel, + &NewCallModel::newIncomingCall, + this, + &ContactModelPimpl::slotIncomingCall); + connect(&callbacksHandler, + &lrc::CallbacksHandler::newAccountMessage, + this, + &ContactModelPimpl::slotNewAccountMessage); + connect(&callbacksHandler, + &CallbacksHandler::transferStatusCreated, + this, + &ContactModelPimpl::slotNewAccountTransfer); + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::profileReceived, + this, + &ContactModelPimpl::slotProfileReceived); + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::userSearchEnded, + this, + &ContactModelPimpl::slotUserSearchEnded); +} + +ContactModelPimpl::~ContactModelPimpl() +{ + disconnect(&callbacksHandler, + &CallbacksHandler::newBuddySubscription, + this, + &ContactModelPimpl::slotNewBuddySubscription); + disconnect(&callbacksHandler, + &CallbacksHandler::contactAdded, + this, + &ContactModelPimpl::slotContactAdded); + disconnect(&callbacksHandler, + &CallbacksHandler::contactRemoved, + this, + &ContactModelPimpl::slotContactRemoved); + disconnect(&callbacksHandler, + &CallbacksHandler::incomingContactRequest, + this, + &ContactModelPimpl::slotIncomingContactRequest); + disconnect(&callbacksHandler, + &CallbacksHandler::registeredNameFound, + this, + &ContactModelPimpl::slotRegisteredNameFound); + disconnect(&*linked.owner.callModel, + &NewCallModel::newIncomingCall, + this, + &ContactModelPimpl::slotIncomingCall); + disconnect(&callbacksHandler, + &lrc::CallbacksHandler::newAccountMessage, + this, + &ContactModelPimpl::slotNewAccountMessage); + disconnect(&callbacksHandler, + &CallbacksHandler::transferStatusCreated, + this, + &ContactModelPimpl::slotNewAccountTransfer); + disconnect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::profileReceived, + this, + &ContactModelPimpl::slotProfileReceived); + disconnect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::userSearchEnded, + this, + &ContactModelPimpl::slotUserSearchEnded); +} + +bool +ContactModelPimpl::fillWithSIPContacts() +{ + auto conversationsForAccount = storage::getAllConversations(db); + for (const auto& convId : conversationsForAccount) { + auto otherParticipants = storage::getPeerParticipantsForConversation(db, convId); + for (const auto& participant : otherParticipants) { + // for each conversations get the other profile id + auto contactInfo = storage::buildContactFromProfile(linked.owner.id, + participant, + profile::Type::SIP); + { + std::lock_guard<std::mutex> lk(contactsMtx_); + contacts.insert(contactInfo.profileInfo.uri, contactInfo); + } + } + } + + return true; +} + +bool +ContactModelPimpl::fillWithJamiContacts() +{ + // Add contacts from daemon + const VectorMapStringString& contacts_vector = ConfigurationManager::instance().getContacts( + linked.owner.id); + for (auto contact_info : contacts_vector) { + std::lock_guard<std::mutex> lk(contactsMtx_); + bool banned = contact_info["banned"] == "true" ? true : false; + addToContacts(contact_info["id"], + linked.owner.profileInfo.type, + "", + banned, + contact_info["conversationId"]); + } + + // Add pending contacts + const VectorMapStringString& pending_tr { + ConfigurationManager::instance().getTrustRequests(linked.owner.id)}; + for (const auto& tr_info : pending_tr) { + // Get pending requests. + auto payload = tr_info[DRing::Account::TrustRequest::PAYLOAD].toUtf8(); + auto contactUri = tr_info[DRing::Account::TrustRequest::FROM]; + auto convId = tr_info[DRing::Account::TrustRequest::CONVERSATIONID]; + if (!convId.isEmpty()) + continue; // This will be added via getConversationsRequests + + auto contactInfo = storage::buildContactFromProfile(linked.owner.id, + contactUri, + profile::Type::PENDING); + + const auto vCard = lrc::vCard::utils::toHashMap(payload); + const auto alias = vCard["FN"]; + QByteArray photo; + for (const auto& key : vCard.keys()) { + if (key.contains("PHOTO") && lrc::api::Lrc::cacheAvatars.load()) + photo = vCard[key]; + } + contactInfo.profileInfo.type = profile::Type::PENDING; + if (!alias.isEmpty()) + contactInfo.profileInfo.alias = alias.constData(); + if (!photo.isEmpty()) + contactInfo.profileInfo.avatar = photo.constData(); + contactInfo.registeredName = ""; + contactInfo.isBanned = false; + + { + std::lock_guard<std::mutex> lk(contactsMtx_); + contacts.insert(contactUri, contactInfo); + } + + // create profile vcard for contact + storage::createOrUpdateProfile(linked.owner.id, contactInfo.profileInfo, true); + } + + // Update presence + // TODO fix this map. This is dumb for now. The map contains values as keys, and empty values. + const VectorMapStringString& subscriptions { + PresenceManager::instance().getSubscriptions(linked.owner.id)}; + for (const auto& subscription : subscriptions) { + auto first = true; + QString uri = ""; + for (const auto& key : subscription) { + if (first) { + first = false; + uri = key; + } else { + { + std::lock_guard<std::mutex> lk(contactsMtx_); + auto it = contacts.find(uri); + if (it != contacts.end()) { + it->isPresent = key == "Online"; + linked.modelUpdated(uri); + } + } + break; + } + } + } + return true; +} + +void +ContactModelPimpl::slotNewBuddySubscription(const QString& accountId, + const QString& contactUri, + bool status) +{ + if (accountId != linked.owner.id) + return; + { + std::lock_guard<std::mutex> lk(contactsMtx_); + auto it = contacts.find(contactUri); + if (it != contacts.end()) { + it->isPresent = status; + } else + return; + } + Q_EMIT linked.modelUpdated(contactUri); +} + +void +ContactModelPimpl::slotContactAdded(const QString& accountId, + const QString& contactUri, + bool confirmed) +{ + if (accountId != linked.owner.id) + return; + auto contact = contacts.find(contactUri); + if (contact != contacts.end()) { + if (contact->profileInfo.type == profile::Type::PENDING) { + Q_EMIT behaviorController.trustRequestTreated(linked.owner.id, contactUri); + } else if (contact->profileInfo.type == profile::Type::JAMI && !contact->isBanned + && confirmed) { + // This means that the peer accepted the trust request. We don't need to re-add the + // contact a second time (and this reset the presence to false). + return; + } + } + // for jams account we already have profile with avatar, use it to save to vCard + bool isJamsAccount = !linked.owner.confProperties.managerUri.isEmpty(); + if (isJamsAccount) { + auto result = searchResult.find(contactUri); + if (result != searchResult.end()) { + storage::createOrUpdateProfile(linked.owner.id, result->profileInfo, true); + } + } + + bool isBanned = false; + + { + // Always get contactsMtx_ lock before bannedContactsMtx_. + std::lock_guard<std::mutex> lk(contactsMtx_); + + { + // Check whether contact is banned or not + std::lock_guard<std::mutex> lk(bannedContactsMtx_); + auto it = std::find(bannedContacts.begin(), bannedContacts.end(), contactUri); + + isBanned = (it != bannedContacts.end()); + + // If contact is banned, do not re-add it, simply update its flag and the banned contacts list + if (isBanned) { + bannedContacts.erase(it); + } + + MapStringString details = ConfigurationManager::instance() + .getContactDetails(linked.owner.id, contactUri); + addToContacts(contactUri, + linked.owner.profileInfo.type, + "", + false, + details["conversationId"]); + } + } + if (isBanned) { + // Update the smartlist + linked.owner.conversationModel->refreshFilter(); + Q_EMIT linked.bannedStatusChanged(contactUri, false); + } else { + Q_EMIT linked.contactAdded(contactUri); + } +} + +void +ContactModelPimpl::slotContactRemoved(const QString& accountId, + const QString& contactUri, + bool banned) +{ + if (accountId != linked.owner.id) + return; + + { + // Always get contactsMtx_ lock before bannedContactsMtx_. + std::lock_guard<std::mutex> lk(contactsMtx_); + + auto contact = contacts.find(contactUri); + if (contact == contacts.end()) + return; + + if (contact->profileInfo.type == profile::Type::PENDING) { + Q_EMIT behaviorController.trustRequestTreated(linked.owner.id, contactUri); + } + + if (contact->profileInfo.type != profile::Type::SIP) + PresenceManager::instance().subscribeBuddy(linked.owner.id, contactUri, false); + + if (banned) { + contact->isBanned = true; + // Update bannedContacts index + bannedContacts.append(contact->profileInfo.uri); + } else { + if (contact->isBanned) { + // Contact was banned, update bannedContacts + std::lock_guard<std::mutex> lk(bannedContactsMtx_); + auto it = std::find(bannedContacts.begin(), + bannedContacts.end(), + contact->profileInfo.uri); + if (it == bannedContacts.end()) { + // should not happen + qDebug("ContactModel::slotContactsRemoved(): Contact is banned but not present " + "in bannedContacts. This is most likely the result of an earlier bug."); + } else { + bannedContacts.erase(it); + } + } + storage::removeContactConversations(db, contactUri); + storage::removeProfile(linked.owner.id, contactUri); + contacts.remove(contactUri); + } + } + + // Update the smartlist + linked.owner.conversationModel->refreshFilter(); + if (banned) { + Q_EMIT linked.bannedStatusChanged(contactUri, true); + } + Q_EMIT linked.contactRemoved(contactUri); +} + +void +ContactModelPimpl::addToContacts(const QString& contactUri, + const profile::Type& type, + const QString& displayName, + bool banned, + const QString& conversationId) +{ + // create a vcard if necessary + profile::Info profileInfo {contactUri, {}, displayName, linked.owner.profileInfo.type}; + auto contactInfo = storage::buildContactFromProfile(linked.owner.id, contactUri, type); + auto updateProfile = false; + if (!profileInfo.alias.isEmpty() && contactInfo.profileInfo.alias != profileInfo.alias) { + updateProfile = true; + contactInfo.profileInfo.alias = profileInfo.alias; + } + auto oldAvatar = lrc::api::Lrc::cacheAvatars.load() + ? contactInfo.profileInfo.avatar + : storage::avatar(linked.owner.id, contactUri); + if (!profileInfo.avatar.isEmpty() && oldAvatar != profileInfo.avatar) { + updateProfile = true; + contactInfo.profileInfo.avatar = profileInfo.avatar; + } + if (updateProfile) + storage::vcard::setProfile(linked.owner.id, contactInfo.profileInfo, true); + + contactInfo.isBanned = banned; + contactInfo.conversationId = conversationId; + if (!lrc::api::Lrc::cacheAvatars.load()) + contactInfo.profileInfo.avatar.clear(); + + // lookup address in case of RING contact + if (type == profile::Type::JAMI) { + ConfigurationManager::instance().lookupAddress(linked.owner.id, "", contactUri); + PresenceManager::instance().subscribeBuddy(linked.owner.id, contactUri, !banned); + } else { + contactInfo.profileInfo.alias = displayName; + } + + contactInfo.profileInfo.type = type; // Because PENDING should not be stored in the database + auto iter = contacts.find(contactInfo.profileInfo.uri); + if (iter != contacts.end()) { + auto info = iter.value(); + contactInfo.registeredName = info.registeredName; + iter.value() = contactInfo; + } else + contacts.insert(iter, contactInfo.profileInfo.uri, contactInfo); + + if (banned) { + bannedContacts.append(contactUri); + } +} + +void +ContactModelPimpl::slotRegisteredNameFound(const QString& accountId, + int status, + const QString& uri, + const QString& registeredName) +{ + if (accountId != linked.owner.id) + return; + + if (status == 0 /* SUCCESS */) { + std::lock_guard<std::mutex> lk(contactsMtx_); + + if (contacts.find(uri) != contacts.end()) { + // update contact and remove temporary item + contacts[uri].registeredName = registeredName; + searchResult.clear(); + } else { + if ((searchQuery != uri && searchQuery != registeredName) || searchQuery.isEmpty()) { + // we are notified that a previous lookup ended + return; + } + auto& temporaryContact = searchResult[uri]; + lrc::api::profile::Info profileInfo = {uri, "", "", profile::Type::TEMPORARY}; + temporaryContact = {profileInfo, registeredName, false, false}; + } + } else { + { + std::lock_guard<std::mutex> lk(contactsMtx_); + if (contacts.find(uri) != contacts.end()) { + // it was lookup for contact + return; + } + } + if ((searchQuery != uri && searchQuery != registeredName) || searchQuery.isEmpty()) { + // we are notified that a previous lookup ended + return; + } + switch (status) { + case 1 /* INVALID */: + updateTemporaryMessage(tr("Invalid ID")); + break; + case 2 /* NOT FOUND */: + updateTemporaryMessage(tr("Username not found")); + break; + case 3 /* ERROR */: + updateTemporaryMessage(tr("Couldn't lookup…")); + break; + } + return; + } + updateTemporaryMessage(""); + Q_EMIT linked.modelUpdated(uri); +} + +void +ContactModelPimpl::slotIncomingContactRequest(const QString& accountId, + const QString& conversationId, + const QString& contactUri, + const QString& payload) +{ + if (linked.owner.id != accountId) + return; + + auto emitTrust = false; + { + std::lock_guard<std::mutex> lk(contactsMtx_); + if (contacts.find(contactUri) == contacts.end()) { + const auto vCard = lrc::vCard::utils::toHashMap(payload.toUtf8()); + const auto alias = vCard["FN"]; + QByteArray photo; + for (const auto& key : vCard.keys()) { + if (key.contains("PHOTO")) + photo = vCard[key]; + } + auto profileInfo = profile::Info {contactUri, photo, alias, profile::Type::PENDING}; + auto contactInfo = contact::Info {profileInfo, "", false, false, false}; + contacts.insert(contactUri, contactInfo); + emitTrust = true; + storage::createOrUpdateProfile(accountId, profileInfo, true); + ConfigurationManager::instance().lookupAddress(linked.owner.id, "", contactUri); + } + } + Q_EMIT linked.incomingContactRequest(contactUri); + if (emitTrust) { + Q_EMIT behaviorController.newTrustRequest(linked.owner.id, conversationId, contactUri); + } +} + +void +ContactModelPimpl::slotIncomingCall(const QString& fromId, + const QString& callId, + const QString& displayname) +{ + bool emitContactAdded = false; + { + std::lock_guard<std::mutex> lk(contactsMtx_); + auto it = contacts.find(fromId); + if (it == contacts.end()) { + // Contact not found, load profile from database. + // The conversation model will create an entry and link the incomingCall. + auto type = (linked.owner.profileInfo.type == profile::Type::JAMI) + ? profile::Type::PENDING + : profile::Type::SIP; + addToContacts(fromId, type, displayname, false); + emitContactAdded = true; + } else { + // Update the display name + if (!displayname.isEmpty()) { + it->profileInfo.alias = displayname; + storage::createOrUpdateProfile(linked.owner.id, it->profileInfo, true); + } + } + } + if (emitContactAdded) { + if (linked.owner.profileInfo.type == profile::Type::SIP) + Q_EMIT linked.contactAdded(fromId); + else if (linked.owner.profileInfo.type == profile::Type::JAMI) + Q_EMIT behaviorController.newTrustRequest(linked.owner.id, "", fromId); + } else + Q_EMIT linked.profileUpdated(fromId); + + Q_EMIT linked.incomingCall(fromId, callId); +} + +void +ContactModelPimpl::slotNewAccountMessage(const QString& accountId, + const QString& peerId, + const QString& msgId, + const MapStringString& payloads) +{ + if (accountId != linked.owner.id) + return; + + QString peerId2(peerId); + + auto emitNewTrust = false; + { + std::lock_guard<std::mutex> lk(contactsMtx_); + if (contacts.find(peerId) == contacts.end()) { + // Contact not found, load profile from database. + // The conversation model will create an entry and link the incomingCall. + + if (linked.owner.profileInfo.type == profile::Type::SIP) { + QString potentialContact = sipUriReceivedFilter(peerId); + if (potentialContact.isEmpty()) { + addToContacts(peerId, profile::Type::SIP, "", false); + } else { + // equivalent uri exist, use that uri + peerId2 = potentialContact; + } + } else { + addToContacts(peerId, profile::Type::PENDING, "", false); + emitNewTrust = true; + } + } + } + if (emitNewTrust) { + Q_EMIT behaviorController.newTrustRequest(linked.owner.id, "", peerId); + } + Q_EMIT linked.newAccountMessage(accountId, peerId2, msgId, payloads); +} + +QString +ContactModelPimpl::sipUriReceivedFilter(const QString& uri) +{ + // this function serves when the uri is not found in the contact list + // return "" means need to add new contact, else means equivalent uri exist + std::string uriCopy = uri.toStdString(); + + auto pos = uriCopy.find("@"); + auto ownerHostName = linked.owner.confProperties.hostname.toStdString(); + + if (pos != std::string::npos) { + // "@" is found, separate username and hostname + std::string hostName = uriCopy.substr(pos + 1); + uriCopy.erase(uriCopy.begin() + pos, uriCopy.end()); + std::string remoteUser = std::move(uriCopy); + + if (hostName.compare(ownerHostName) == 0) { + auto remoteUserQStr = QString::fromStdString(remoteUser); + if (contacts.find(remoteUserQStr) != contacts.end()) { + return remoteUserQStr; + } + if (remoteUser.at(0) == '+') { + // "+" - country dial-in codes + // maximum 3 digits + for (int i = 2; i <= 4; i++) { + QString tempUserName = QString::fromStdString(remoteUser.substr(i)); + if (contacts.find(tempUserName) != contacts.end()) { + return tempUserName; + } + } + return ""; + } else { + // if not "+" from incoming + // sub "+" char from contacts to see if user exit + for (auto& contactUri : contacts.keys()) { + if (!contactUri.isEmpty()) { + for (int j = 2; j <= 4; j++) { + if (QString(contactUri).remove(0, j) == remoteUserQStr) { + return contactUri; + } + } + } + } + return ""; + } + } + // different hostname means not a phone number + // no need to check country dial-in codes + return ""; + } + // "@" is not found -> not possible since all response uri has one + return ""; +} + +void +ContactModelPimpl::slotNewAccountTransfer(const QString& fileId, datatransfer::Info info) +{ + if (info.accountId != linked.owner.id) + return; + + bool emitNewTrust = false; + { + std::lock_guard<std::mutex> lk(contactsMtx_); + // Note: just add a contact for compatibility (so not for swarm). + if (info.conversationId.isEmpty() && !info.peerUri.isEmpty() + && contacts.find(info.peerUri) == contacts.end()) { + // Contact not found, load profile from database. + // The conversation model will create an entry and link the incomingCall. + auto type = (linked.owner.profileInfo.type == profile::Type::JAMI) + ? profile::Type::PENDING + : profile::Type::SIP; + addToContacts(info.peerUri, type, "", false); + emitNewTrust = (linked.owner.profileInfo.type == profile::Type::JAMI); + } + } + if (emitNewTrust) { + Q_EMIT behaviorController.newTrustRequest(linked.owner.id, "", info.peerUri); + } + + Q_EMIT linked.newAccountTransfer(fileId, info); +} + +void +ContactModelPimpl::slotProfileReceived(const QString& accountId, + const QString& peer, + const QString& path) +{ + if (accountId != linked.owner.id) + return; + + QFile vCardFile(path); + if (!vCardFile.open(QIODevice::ReadOnly | QIODevice::Text)) + return; + QTextStream in(&vCardFile); + + auto vCard = in.readAll(); + + profile::Info profileInfo; + profileInfo.uri = peer; + profileInfo.type = profile::Type::JAMI; + + for (auto& e : QString(vCard).split("\n")) + if (e.contains("PHOTO")) + profileInfo.avatar = e.split(":")[1]; + else if (e.contains("FN")) + profileInfo.alias = e.split(":")[1]; + + if (peer == linked.owner.profileInfo.uri) { + if (linked.owner.profileInfo.avatar.isEmpty() && !profileInfo.avatar.isEmpty()) { + auto dest = storage::getPath() + accountId + "/profile.vcf"; + QFile oldvCard(dest); + if (oldvCard.exists()) + oldvCard.remove(); + vCardFile.rename(dest); + linked.owner.accountModel->setAlias(linked.owner.id, profileInfo.alias); + linked.owner.accountModel->setAvatar(linked.owner.id, profileInfo.avatar); + Q_EMIT linked.profileUpdated(peer); + } + return; + } + vCardFile.remove(); + + contact::Info contactInfo; + contactInfo.profileInfo = profileInfo; + + linked.owner.contactModel->addContact(contactInfo); + if (!lrc::api::Lrc::cacheAvatars.load()) + contactInfo.profileInfo.avatar.clear(); // Do not store after update +} + +void +ContactModelPimpl::slotUserSearchEnded(const QString& accountId, + int status, + const QString& query, + const VectorMapStringString& result) +{ + if (searchQuery != query) + return; + if (accountId != linked.owner.id) + return; + searchResult.clear(); + switch (status) { + case 0: /* SUCCESS */ + for (auto& resultInfo : result) { + if (contacts.find(resultInfo.value("id")) != contacts.end()) { + continue; + } + profile::Info profileInfo; + profileInfo.uri = resultInfo.value("id"); + profileInfo.type = profile::Type::TEMPORARY; + profileInfo.avatar = resultInfo.value("profilePicture"); + profileInfo.alias = resultInfo.value("firstName") + " " + resultInfo.value("lastName"); + contact::Info contactInfo; + contactInfo.profileInfo = profileInfo; + contactInfo.registeredName = resultInfo.value("username"); + searchResult.insert(profileInfo.uri, contactInfo); + } + updateTemporaryMessage(""); + break; + case 3: /* ERROR */ + updateTemporaryMessage("could not find contact matching search"); + break; + default: + break; + } + Q_EMIT linked.modelUpdated(query); +} + +} // namespace lrc + +#include "api/moc_contactmodel.cpp" +#include "contactmodel.moc" diff --git a/src/libclient/containerview.h b/src/libclient/containerview.h new file mode 100644 index 0000000000000000000000000000000000000000..b3e31d97b57cd0c288cee52a6b3b6fe3d7e974dd --- /dev/null +++ b/src/libclient/containerview.h @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2020-2022 by Savoir-faire Linux + * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "typedefs.h" + +#include <algorithm> +#include <functional> +#include <iostream> +#include <iterator> +#include <optional> +#include <type_traits> + +template<class T> +using OptRef = typename std::optional<std::reference_wrapper<T>>; + +// Some SFINAE helpers to clarify what happened when someone tries +// to make a ContainerView<float> or something wacky like that. +namespace detail { +template<typename... Ts> +struct has_defs +{}; +template<typename T, typename _ = void> +struct is_container : std::false_type +{}; +template<typename T> +struct is_container<T, + std::conditional_t<false, + has_defs<decltype(std::declval<T>().front()), + decltype(std::declval<T>().begin()), + decltype(std::declval<T>().end())>, + void>> : public std::true_type +{}; +} // namespace detail + +// Extra compile-time check to clarify why compilation has failed. +// Otherwise, the error message will be "'x' uses undefined struct ContainerView<decltype(x), void>" +template<class BaseType, class Enable = void> +struct ContainerView +{ + static_assert(detail::is_container<BaseType>::value == true, + "Template parameter is probably not a container!"); +}; + +template<class BaseType> +struct ContainerView<BaseType, std::enable_if_t<detail::is_container<BaseType>::value>> +{ +private: + // Form a type by rebinding the underlying container type to a reference + // wrapped value type. + template<class ContainerType, class NewType> + struct rebind; + + template<class ValueType, class... Args, template<class...> class ContainerType, class NewType> + struct rebind<ContainerType<ValueType, Args...>, NewType> + { + using type = ContainerType<NewType, typename rebind<Args, NewType>::type...>; + }; + + using value_type = std::remove_reference_t<decltype(std::declval<BaseType>().front())>; + using const_reference = const value_type&; + using view_type = typename rebind<BaseType, std::reference_wrapper<value_type>>::type; + +public: + using FilterCallback = std::function<bool(const_reference)>; + using SortCallback = std::function<bool(const_reference, const_reference)>; + using OnEntryCallback = std::function<void(const_reference)>; + + ContainerView() = default; + ContainerView(const BaseType& container) + { + data_ = std::make_optional(std::ref(container)); + auto& dataSource = std::remove_const_t<BaseType&>(data()); + view_.assign(dataSource.begin(), dataSource.end()); + }; + ContainerView(const ContainerView& other) + : data_(std::nullopt) + , view_(other().begin(), other().end()) + , dirty_(other.dirty_) + , sortCallback_(other.sortCallback_) + , filterCallback_(other.filterCallback_) {}; + ContainerView& operator=(const ContainerView& other) = default; + ContainerView& operator=(ContainerView&& other) = default; + ContainerView(ContainerView&& other) noexcept = default; + + // Allow concatenation of views. + ContainerView& operator+=(const ContainerView& rhs) + { + view_.insert(view_.cend(), rhs.get().cbegin(), rhs.get().cend()); + return *this; + } + friend ContainerView operator+(ContainerView lhs, const ContainerView& rhs) + { + lhs += rhs; + return lhs; + } + + // Reset the underlying container and initialize the view. + ContainerView& reset(const BaseType& container) + { + data_ = std::make_optional(std::ref(container)); + auto& dataSource = std::remove_const_t<BaseType&>(data()); + view_.assign(dataSource.begin(), dataSource.end()); + invalidate(); + return *this; + } + + // Alternately, reset the view to another view and disregard underlying data. + ContainerView& reset(const ContainerView& other) + { + data_ = std::nullopt; + auto& dataSource = std::remove_const_t<ContainerView&>(other); + view_.assign(dataSource.get().begin(), dataSource.get().end()); + invalidate(); + return *this; + } + + // Sort the reference wrapped elements of the view container with the + // given predicate or the stored one. + ContainerView& sort(SortCallback&& pred = {}) + { + if (!dirty_) { + std::cout << "view not dirty, no-op sort" << std::endl; + return *this; + } + if (auto&& sortCallback = pred ? pred : sortCallback_) + std::sort(view_.begin(), view_.end(), sortCallback); + else + std::cout << "no sort function specified or bound" << std::endl; + return *this; + } + + // Filter the reference wrapped elements of the view container with the + // given predicate or the stored one. + // Only done if the view has been invalidated(e.g. the underlying container + // has been updated) + ContainerView& filter(FilterCallback&& pred = {}) + { + if (!dirty_) { + std::cout << "view not dirty, no-op filter" << std::endl; + return *this; + } + if (auto&& filterCallback = pred ? pred : filterCallback_) { + if (data_.has_value()) { + auto& dataSource = std::remove_const_t<BaseType&>(data()); + applyFilter(dataSource, filterCallback); + } else { + auto viewSource = view_; + applyFilter(viewSource, filterCallback); + } + } else + std::cout << "no filter function specified or bound" << std::endl; + return *this; + } + + // Iterate over the the reference wrapped elements of the view container + // and execute a callback on each element. + ContainerView& for_each(OnEntryCallback&& pred) + { + for (const auto& e : view_) + pred(e); + return *this; + } + + // Store a non-static member function as a SortCallback. + // The member function must match that of a binary predicate. + template<typename T, typename... Args> + void bindSortCallback(T* inst, bool (T::*func)(Args...)) + { + bindCallback(sortCallback_, inst, func); + } + // Overload for function objects. + template<typename Func = SortCallback> + void bindSortCallback(Func&& func) + { + sortCallback_ = func; + } + + // Store a non-static member function as a FilterCallback. + // The member function must match that of a unary predicate. + template<typename T, typename... Args> + void bindFilterCallback(T* inst, bool (T::*func)(Args...)) + { + bindCallback(filterCallback_, inst, func); + } + // Overload for function objects. + template<typename Func = FilterCallback> + void bindFilterCallback(Func&& func) + { + filterCallback_ = func; + } + + // Basic container operations should be avoided. + size_t size() const { return view_.size(); } + const_reference at(size_t pos) const { return view_.at(pos); } + void clear() { view_.clear(); } + + // TODO: re-filtering ?? should maybe observe underlying data in order to + // not track this manually. + bool isDirty() const noexcept { return dirty_; }; + ContainerView& invalidate() noexcept + { + dirty_ = true; + return *this; + }; + ContainerView& validate() noexcept + { + dirty_ = false; + return *this; + }; + + // Returns whether or not this view has a concrete data source + // or is just a view of a view. + constexpr bool hasUnderlyingData() const noexcept { return data_.has_value(); } + + // Access the view. + constexpr const view_type& operator()() const noexcept { return view_; } + constexpr const view_type& get() const noexcept { return view_; } + +private: + // A reference to the optional underlying container data source. + // If not used, the view can be constructed from another proxy + // container view, and refiltered and sorted. + OptRef<const BaseType> data_; + + // The 'view' is a container of reference wrapped values suitable + // for container operations like sorting and filtering. + view_type view_; + + // TODO: remove this invalidation flag if possible. + bool dirty_ {true}; + + // Stores the sorting/filtering predicates that can be re-applied + // instead of passing a lambda as a parameter to sort(). + FilterCallback filterCallback_ {}; + + // Same as above but for sorting. + SortCallback sortCallback_ {}; + + // A generic non-static member function storing function. + template<typename C, typename T, typename... Args> + void bindCallback(C& callback, T* inst, bool (T::*func)(Args...)) + { + // Using a lambda instead of std::bind works better for functions with an + // unknown number of parameters. e.g. callback = std::bind(func, inst, _1, ???); + callback = [=](Args... args) -> bool { + return (inst->*func)(args...); + }; + } + + // Hard unbox and unwrap underlying data container. + const BaseType& data() { + //this fix error when build for macOS 10.13(error: 'value' is unavailable: introduced in macOS 10.14) + #ifdef __APPLE__ + if(!data_.has_value()) + throw std::logic_error("bad optional access"); + return *data_; + #else + return data_.value().get(); + #endif + } + + // Actually filter the view. + template<typename T, typename Func = FilterCallback> + ContainerView& applyFilter(T& source, Func&& pred) + { + view_.clear(); + std::copy_if(source.begin(), source.end(), std::back_inserter(view_), pred); + return *this; + } +}; diff --git a/src/libclient/conversationmodel.cpp b/src/libclient/conversationmodel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..06245505b60f8f3c816f239520298c1b6761503d --- /dev/null +++ b/src/libclient/conversationmodel.cpp @@ -0,0 +1,4194 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com> * + * Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#include "api/conversationmodel.h" + +// LRC +#include "api/lrc.h" +#include "api/behaviorcontroller.h" +#include "api/contactmodel.h" +#include "api/newcallmodel.h" +#include "api/newaccountmodel.h" +#include "api/account.h" +#include "api/call.h" +#include "api/datatransfer.h" +#include "api/datatransfermodel.h" +#include "callbackshandler.h" +#include "containerview.h" +#include "authority/storagehelper.h" +#include "uri.h" + +// Dbus +#include "dbus/configurationmanager.h" +#include "dbus/callmanager.h" + +// daemon +#include <account_const.h> +#include <datatransfer_interface.h> + +// Qt +#include <QtCore/QTimer> +#include <QFileInfo> + +// std +#include <algorithm> +#include <mutex> +#include <regex> +#include <fstream> +#include <sstream> + +namespace lrc { + +using namespace authority; +using namespace api; + +class ConversationModelPimpl : public QObject +{ + Q_OBJECT +public: + ConversationModelPimpl(const ConversationModel& linked, + Lrc& lrc, + Database& db, + const CallbacksHandler& callbacksHandler, + const BehaviorController& behaviorController); + + ~ConversationModelPimpl(); + + using FilterPredicate = std::function<bool(const conversation::Info& convInfo)>; + + /** + * return a conversation index from conversations or -1 if no index is found. + * @param uid of the contact to search. + * @return an int. + */ + int indexOf(const QString& uid) const; + + /** + * return a reference to a conversation with given filter + * @param pred a unary comparison predicate with which to find the conversation + * @param searchResultIncluded if need to search in contacts and userSearch + * @return a reference to a conversation with given uid + */ + std::reference_wrapper<conversation::Info> getConversation( + const FilterPredicate& pred, const bool searchResultIncluded = false) const; + + /** + * return a reference to a conversation with given uid. + * @param conversation uid. + * @param searchResultIncluded if need to search in contacts and userSearch. + * @return a reference to a conversation with the given uid. + */ + std::reference_wrapper<conversation::Info> getConversationForUid( + const QString& uid, const bool searchResultIncluded = false) const; + + /** + * return a reference to a conversation with participant. + * @param participant uri. + * @param searchResultIncluded if need to search in contacts and userSearch. + * @return a reference to a conversation with the given peer uri. + * @warning we could have multiple swarm conversations for the same peer. This function will + * return an active one-to-one conversation. + */ + std::reference_wrapper<conversation::Info> getConversationForPeerUri( + const QString& uri, const bool searchResultIncluded = false) const; + /** + * return a vector of conversation indices for the given contact uri empty + * if no index is found + * @param uri of the contact to search + * @param writable whether or not to exclude read-only conversations(use for interactions) + * @return an vector of indices + */ + std::vector<int> getIndicesForContact(const QString& uri, bool writable = false) const; + /** + * Initialize conversations_ and filteredConversations_ + */ + void initConversations(); + /** + * Filter all conversations + */ + bool filter(const conversation::Info& conv); + /** + * Sort conversation by last action + */ + bool sort(const conversation::Info& convA, const conversation::Info& convB); + /** + * Call contactModel.addContact if necessary + * @param contactUri + */ + void sendContactRequest(const QString& contactUri); + /** + * Add a conversation with contactUri + * @param convId + * @param contactUri + */ + void addConversationWith(const QString& convId, const QString& contactUri, bool isRequest); + /** + * Add a swarm conversation to conversation list + * @param convId + */ + void addSwarmConversation(const QString& convId); + /** + * Add call interaction for conversation with callId + * @param callId + * @param duration + */ + void addOrUpdateCallMessage(const QString& callId, + const QString& from, + bool incoming, + const std::time_t& duration = -1); + /** + * Add a new message from a peer in the database + * @param peerId the author id + * @param body the content of the message + * @param timestamp the timestamp of the message + * @param daemonId the daemon id + * @return msgId generated (in db) + */ + QString addIncomingMessage(const QString& peerId, + const QString& body, + const uint64_t& timestamp = 0, + const QString& daemonId = ""); + /** + * Change the status of an interaction. Listen from callbacksHandler + * @param accountId, account linked + * @param messageId, interaction to update + * @param conversationId, conversation + * @param peerId, peer id + * @param status, new status for this interaction + */ + void slotUpdateInteractionStatus(const QString& accountId, + const QString& conversationId, + const QString& peerId, + const QString& messageId, + int status); + + /** + * place a call + * @param uid, conversation id + * @param isAudioOnly, allow to specify if the call is only audio. Set to false by default. + */ + void placeCall(const QString& uid, bool isAudioOnly = false); + + /** + * get number of unread messages + */ + int getNumberOfUnreadMessagesFor(const QString& uid); + + /** + * Handle data transfer progression + */ + void updateTransferProgress(QTimer* timer, + const QString& conversation, + int conversationIdx, + const QString& interactionId); + + bool usefulDataFromDataTransfer(const QString& fileId, + const datatransfer::Info& info, + QString& interactionId, + QString& conversationId); + void awaitingHost(const QString& fileId, datatransfer::Info info); + + bool hasOneOneSwarmWith(const QString& participant); + + /** + * accept a file transfer + * @param convUid + * @param interactionId + * @param final name of the file + */ + void acceptTransfer(const QString& convUid, const QString& interactionId, const QString& path); + void handleIncomingFile(const QString& convId, + const QString& interactionId, + const QString& displayName, + int totalSize); + void addConversationRequest(const MapStringString& convRequest); + void addContactRequest(const QString& contactUri); + + // filter out ourself from conversation participants. + const VectorString peersForConversation(const conversation::Info& conversation) const; + // insert swarm interactions. Return false if interaction already exists. + bool insertSwarmInteraction(const QString& interactionId, + const interaction::Info& interaction, + conversation::Info& conversation, + bool insertAtBegin); + void invalidateModel(); + void emplaceBackConversation(conversation::Info&& conversation); + void eraseConversation(const QString& convId); + void eraseConversation(int index); + + const ConversationModel& linked; + Lrc& lrc; + Database& db; + const CallbacksHandler& callbacksHandler; + const BehaviorController& behaviorController; + + ConversationModel::ConversationQueue conversations; ///< non-filtered conversations + ConversationModel::ConversationQueue searchResults; + + ConversationModel::ConversationQueueProxy filteredConversations; + ConversationModel::ConversationQueueProxy customFilteredConversations; + + QString currentFilter; + FilterType typeFilter; + FilterType customTypeFilter; + + std::map<QString, std::mutex> interactionsLocks; ///< {convId, mutex} + MapStringString transfIdToDbIntId; + +public Q_SLOTS: + /** + * Listen from contactModel when updated (like new alias, avatar, etc.) + */ + void slotContactModelUpdated(const QString& uri); + /** + * Listen from contactModel when a new contact is added + * @param uri + */ + void slotContactAdded(const QString& contactUri); + /** + * Listen from contactModel when receive a new contact request + * @param uri + */ + void slotIncomingContactRequest(const QString& contactUri); + /** + * Listen from contactModel when a pending contact is accepted + * @param uri + */ + void slotPendingContactAccepted(const QString& uri); + /** + * Listen from contactModel when aa new contact is removed + * @param uri + */ + void slotContactRemoved(const QString& uri); + /** + * Listen from callmodel for new calls. + * @param fromId caller uri + * @param callId + */ + void slotIncomingCall(const QString& fromId, const QString& callId); + /** + * Listen from callmodel for calls status changed. + * @param callId + */ + void slotCallStatusChanged(const QString& callId, int code); + /** + * Listen from callmodel for writing "Call started" + * @param callId + */ + void slotCallStarted(const QString& callId); + /** + * Listen from callmodel for writing "Call ended" + * @param callId + */ + void slotCallEnded(const QString& callId); + /** + * Listen from CallbacksHandler for new incoming interactions; + * @param accountId + * @param msgId + * @param peerId + * @param payloads body + */ + void slotNewAccountMessage(const QString& accountId, + const QString& peerId, + const QString& msgId, + const MapStringString& payloads); + /** + * Listen from CallbacksHandler for new messages in a SIP call + * @param accountId account linked to the interaction + * @param callId call linked to the interaction + * @param from author uri + * @param body of the message + */ + void slotIncomingCallMessage(const QString& accountId, + const QString& callId, + const QString& from, + const QString& body); + /** + * Listen from CallModel when a call is added to a conference + * @param callId + * @param confId + */ + void slotCallAddedToConference(const QString& callId, const QString& confId); + /** + * Listen from CallbacksHandler when a conference is deleted. + * @param accountId + * @param confId + */ + void slotConferenceRemoved(const QString& accountId, const QString& confId); + /** + * Listen for when a contact is composing + * @param accountId + * @param contactUri + * @param isComposing + */ + void slotComposingStatusChanged(const QString& accountId, + const QString& convId, + const QString& contactUri, + bool isComposing); + + void slotTransferStatusCreated(const QString& fileId, api::datatransfer::Info info); + void slotTransferStatusCanceled(const QString& fileId, api::datatransfer::Info info); + void slotTransferStatusAwaitingPeer(const QString& fileId, api::datatransfer::Info info); + void slotTransferStatusAwaitingHost(const QString& fileId, api::datatransfer::Info info); + void slotTransferStatusOngoing(const QString& fileId, api::datatransfer::Info info); + void slotTransferStatusFinished(const QString& fileId, api::datatransfer::Info info); + void slotTransferStatusError(const QString& fileId, api::datatransfer::Info info); + void slotTransferStatusTimeoutExpired(const QString& fileId, api::datatransfer::Info info); + void slotTransferStatusUnjoinable(const QString& fileId, api::datatransfer::Info info); + bool updateTransferStatus(const QString& fileId, + datatransfer::Info info, + interaction::Status newStatus, + bool& updated); + void slotConversationLoaded(uint32_t requestId, + const QString& accountId, + const QString& conversationId, + const VectorMapStringString& messages); + void slotMessageReceived(const QString& accountId, + const QString& conversationId, + const MapStringString& message); + void slotConversationRequestReceived(const QString& accountId, + const QString& conversationId, + const MapStringString& metadatas); + void slotConversationRequestDeclined(const QString& accountId, const QString& conversationId); + void slotConversationMemberEvent(const QString& accountId, + const QString& conversationId, + const QString& memberUri, + int event); + void slotConversationReady(const QString& accountId, const QString& conversationId); + void slotConversationRemoved(const QString& accountId, const QString& conversationId); +}; + +ConversationModel::ConversationModel(const account::Info& owner, + Lrc& lrc, + Database& db, + const CallbacksHandler& callbacksHandler, + const BehaviorController& behaviorController) + : QObject(nullptr) + , pimpl_(std::make_unique<ConversationModelPimpl>(*this, + lrc, + db, + callbacksHandler, + behaviorController)) + , owner(owner) +{} + +void +ConversationModel::initConversations() +{ + pimpl_->initConversations(); +} + +ConversationModel::~ConversationModel() {} + +const ConversationModel::ConversationQueue& +ConversationModel::getConversations() const +{ + return pimpl_->conversations; +} + +const ConversationModel::ConversationQueueProxy& +ConversationModel::allFilteredConversations() const +{ + if (!pimpl_->filteredConversations.isDirty()) + return pimpl_->filteredConversations; + + return pimpl_->filteredConversations.filter().sort().validate(); +} + +QMap<ConferenceableItem, ConferenceableValue> +ConversationModel::getConferenceableConversations(const QString& convId, const QString& filter) const +{ + auto conversationIdx = pimpl_->indexOf(convId); + if (conversationIdx == -1 || !owner.enabled) { + return {}; + } + QMap<ConferenceableItem, ConferenceableValue> result; + ConferenceableValue callsVector, contactsVector; + + auto currentConfId = pimpl_->conversations.at(conversationIdx).confId; + auto currentCallId = pimpl_->conversations.at(conversationIdx).callId; + auto calls = pimpl_->lrc.getCalls(); + auto conferences = pimpl_->lrc.getConferences(owner.id); + auto& conversations = pimpl_->conversations; + auto currentAccountID = pimpl_->linked.owner.id; + // add contacts for current account + for (const auto& conv : conversations) { + // conversations with calls will be added in call section + // we want to add only contacts non-swarm or one-to-one conversation + auto& peers = pimpl_->peersForConversation(conv); + if (!conv.callId.isEmpty() || !conv.confId.isEmpty() || !conv.isCoreDialog() + || peers.empty()) { + continue; + } + try { + auto contact = owner.contactModel->getContact(peers.front()); + if (contact.isBanned || contact.profileInfo.type == profile::Type::PENDING) { + continue; + } + QVector<AccountConversation> cv; + AccountConversation accConv = {conv.uid, currentAccountID}; + cv.push_back(accConv); + if (filter.isEmpty()) { + contactsVector.push_back(cv); + continue; + } + bool result = contact.profileInfo.alias.contains(filter, Qt::CaseInsensitive) + || contact.profileInfo.uri.contains(filter, Qt::CaseInsensitive) + || contact.registeredName.contains(filter, Qt::CaseInsensitive); + if (result) { + contactsVector.push_back(cv); + } + } catch (const std::out_of_range& e) { + qDebug() << e.what(); + continue; + } + } + + if (calls.empty() && conferences.empty()) { + result.insert(ConferenceableItem::CONTACT, contactsVector); + return result; + } + + // filter out calls from conference + for (const auto& c : conferences) { + for (const auto& subcall : owner.callModel->getConferenceSubcalls(c)) { + auto position = std::find(calls.begin(), calls.end(), subcall); + if (position != calls.end()) { + calls.erase(position); + } + } + } + + // found conversations and account for calls and conferences + QMap<QString, QVector<AccountConversation>> tempConferences; + for (const auto& account_id : pimpl_->lrc.getAccountModel().getAccountList()) { + try { + auto& accountInfo = pimpl_->lrc.getAccountModel().getAccountInfo(account_id); + auto type = accountInfo.profileInfo.type == profile::Type::SIP ? FilterType::SIP + : FilterType::JAMI; + auto accountConv = accountInfo.conversationModel->getFilteredConversations(type); + accountConv.for_each([this, + filter, + &accountInfo, + account_id, + currentCallId, + currentConfId, + &conferences, + &calls, + &tempConferences, + &callsVector](const conversation::Info& conv) { + bool confFilterPredicate = !conv.confId.isEmpty() && conv.confId != currentConfId + && std::find(conferences.begin(), + conferences.end(), + conv.confId) + != conferences.end(); + bool callFilterPredicate = !conv.callId.isEmpty() && conv.callId != currentCallId + && std::find(calls.begin(), calls.end(), conv.callId) + != calls.end(); + auto& peers = pimpl_->peersForConversation(conv); + if ((!confFilterPredicate && !callFilterPredicate) || !conv.isCoreDialog()) { + return; + } + + // vector of conversationID accountID pair + // for call has only one entry, for conference multyple + QVector<AccountConversation> cv; + AccountConversation accConv = {conv.uid, account_id}; + cv.push_back(accConv); + + bool isConference = !conv.confId.isEmpty(); + // call could be added if it is not conference and in active state + bool shouldAddCall = false; + if (!isConference && accountInfo.callModel->hasCall(conv.callId)) { + const auto& call = accountInfo.callModel->getCall(conv.callId); + shouldAddCall = call.status == lrc::api::call::Status::PAUSED + || call.status == lrc::api::call::Status::IN_PROGRESS; + } + + auto contact = accountInfo.contactModel->getContact(peers.front()); + // check if contact satisfy filter + bool result = (filter.isEmpty() || isConference) + ? true + : (contact.profileInfo.alias.contains(filter) + || contact.profileInfo.uri.contains(filter) + || contact.registeredName.contains(filter)); + if (!result) { + return; + } + if (isConference && tempConferences.count(conv.confId)) { + tempConferences.find(conv.confId).value().push_back(accConv); + } else if (isConference) { + tempConferences.insert(conv.confId, cv); + } else if (shouldAddCall) { + callsVector.push_back(cv); + } + }); + } catch (...) { + } + } + for (auto it : tempConferences.toStdMap()) { + if (filter.isEmpty()) { + callsVector.push_back(it.second); + continue; + } + for (AccountConversation accConv : it.second) { + try { + auto& account = pimpl_->lrc.getAccountModel().getAccountInfo(accConv.accountId); + auto& conv = account.conversationModel->getConversationForUid(accConv.convId)->get(); + auto& peers = pimpl_->peersForConversation(conv); + if (!conv.isCoreDialog()) { + continue; + } + auto cont = account.contactModel->getContact(peers.front()); + if (cont.profileInfo.alias.contains(filter) || cont.profileInfo.uri.contains(filter) + || cont.registeredName.contains(filter)) { + callsVector.push_back(it.second); + continue; + } + } catch (...) { + } + } + } + result.insert(ConferenceableItem::CALL, callsVector); + result.insert(ConferenceableItem::CONTACT, contactsVector); + return result; +} + +const ConversationModel::ConversationQueue& +ConversationModel::getAllSearchResults() const +{ + return pimpl_->searchResults; +} + +const ConversationModel::ConversationQueueProxy& +ConversationModel::getFilteredConversations(const FilterType& filter, + bool forceUpdate, + const bool includeBanned) const +{ + if (pimpl_->customTypeFilter == filter && !pimpl_->customFilteredConversations.isDirty() + && !forceUpdate) + return pimpl_->customFilteredConversations; + + pimpl_->customTypeFilter = filter; + return pimpl_->customFilteredConversations.reset(pimpl_->conversations) + .filter([this, &includeBanned](const conversation::Info& entry) { + try { + if (entry.isLegacy()) { + auto& peers = pimpl_->peersForConversation(entry); + if (peers.isEmpty()) { + return false; + } + auto contactInfo = owner.contactModel->getContact(peers.front()); + // do not check blocked contacts for conversation with many participants + if (!includeBanned && (contactInfo.isBanned && peers.size() == 1)) + return false; + } + switch (pimpl_->customTypeFilter) { + case FilterType::JAMI: + // we have conversation with many participants only for JAMI + return (owner.profileInfo.type == profile::Type::JAMI && !entry.isRequest); + case FilterType::SIP: + return (owner.profileInfo.type == profile::Type::SIP && !entry.isRequest); + case FilterType::REQUEST: + return entry.isRequest; + case FilterType::INVALID: + default: + break; + } + } catch (...) { + } + return false; + }) + .validate(); +} + +const ConversationModel::ConversationQueueProxy& +ConversationModel::getFilteredConversations(const profile::Type& profileType, + bool forceUpdate, + const bool includeBanned) const +{ + FilterType filterType = FilterType::INVALID; + switch (profileType) { + case lrc::api::profile::Type::JAMI: + filterType = lrc::api::FilterType::JAMI; + break; + case lrc::api::profile::Type::SIP: + filterType = lrc::api::FilterType::SIP; + break; + default: + break; + } + + return getFilteredConversations(filterType, forceUpdate, includeBanned); +} + +OptRef<conversation::Info> +ConversationModel::getConversationForUid(const QString& uid) const +{ + try { + return std::make_optional(pimpl_->getConversationForUid(uid, true)); + } catch (const std::out_of_range&) { + return std::nullopt; + } +} + +OptRef<conversation::Info> +ConversationModel::getConversationForPeerUri(const QString& uri) const +{ + try { + return std::make_optional(pimpl_->getConversation( + [this, uri](const conversation::Info& conv) -> bool { + if (!conv.isCoreDialog()) { + return false; + } + if (conv.mode == conversation::Mode::ONE_TO_ONE) { + return pimpl_->peersForConversation(conv).indexOf(uri) != -1; + } + return uri == pimpl_->peersForConversation(conv).front(); + }, + true)); + } catch (const std::out_of_range&) { + return std::nullopt; + } +} + +OptRef<conversation::Info> +ConversationModel::getConversationForCallId(const QString& callId) const +{ + try { + return std::make_optional(pimpl_->getConversation( + [callId](const conversation::Info& conv) -> bool { + return (callId == conv.callId || callId == conv.confId); + }, + true)); + } catch (const std::out_of_range&) { + return std::nullopt; + } +} + +OptRef<conversation::Info> +ConversationModel::filteredConversation(unsigned row) const +{ + auto conversations = allFilteredConversations(); + if (row >= conversations.get().size()) + return std::nullopt; + + return std::make_optional(conversations.get().at(row)); +} + +OptRef<conversation::Info> +ConversationModel::searchResultForRow(unsigned row) const +{ + auto& results = pimpl_->searchResults; + if (row >= results.size()) + return std::nullopt; + + return std::make_optional(std::ref(results.at(row))); +} + +void +ConversationModel::makePermanent(const QString& uid) +{ + try { + auto& conversation = pimpl_->getConversationForUid(uid, true).get(); + + if (conversation.participants.empty()) { + // Should not + qDebug() << "ConversationModel::addConversation can't add a conversation with no " + "participant"; + return; + } + + // Send contact request if non used + auto& peers = pimpl_->peersForConversation(conversation); + if (peers.size() != 1) { + return; + } + pimpl_->sendContactRequest(peers.front()); + } catch (const std::out_of_range& e) { + qDebug() << "make permanent failed. conversation not found"; + } +} + +void +ConversationModel::selectConversation(const QString& uid) const +{ + try { + auto& conversation = pimpl_->getConversationForUid(uid, true).get(); + + bool callEnded = true; + if (!conversation.callId.isEmpty()) { + try { + auto call = owner.callModel->getCall(conversation.callId); + callEnded = call.status == call::Status::ENDED; + } catch (...) { + } + } + if (!conversation.confId.isEmpty() && owner.confProperties.isRendezVous) { + // If we are on a rendez vous account and we select the conversation, + // attach to the call. + CallManager::instance().unholdConference(owner.id, conversation.confId); + } + + if (not callEnded and not conversation.confId.isEmpty()) { + Q_EMIT pimpl_->behaviorController.showCallView(owner.id, conversation.uid); + } else if (callEnded) { + Q_EMIT pimpl_->behaviorController.showChatView(owner.id, conversation.uid); + } else { + try { + auto call = owner.callModel->getCall(conversation.callId); + switch (call.status) { + case call::Status::INCOMING_RINGING: + case call::Status::OUTGOING_RINGING: + case call::Status::CONNECTING: + case call::Status::SEARCHING: + // We are currently in a call + Q_EMIT pimpl_->behaviorController.showIncomingCallView(owner.id, conversation.uid); + break; + case call::Status::PAUSED: + case call::Status::CONNECTED: + case call::Status::IN_PROGRESS: + // We are currently receiving a call + Q_EMIT pimpl_->behaviorController.showCallView(owner.id, conversation.uid); + break; + case call::Status::PEER_BUSY: + Q_EMIT pimpl_->behaviorController.showLeaveMessageView(owner.id, conversation.uid); + break; + case call::Status::TIMEOUT: + case call::Status::TERMINATING: + case call::Status::INVALID: + case call::Status::INACTIVE: + // call just ended + Q_EMIT pimpl_->behaviorController.showChatView(owner.id, conversation.uid); + break; + case call::Status::ENDED: + default: // ENDED + // nothing to do + break; + } + } catch (const std::out_of_range&) { + // Should not happen + Q_EMIT pimpl_->behaviorController.showChatView(owner.id, conversation.uid); + } + } + } catch (const std::out_of_range& e) { + qDebug() << "select conversation failed. conversation not exists"; + } +} + +void +ConversationModel::removeConversation(const QString& uid, bool banned) +{ + // Get conversation + auto conversationIdx = pimpl_->indexOf(uid); + if (conversationIdx == -1) + return; + + auto& conversation = pimpl_->conversations.at(conversationIdx); + // Remove contact from daemon + // NOTE: this will also remove the conversation into the database for non-swarm and remove + // conversation repository for one-to-one. + auto& peers = pimpl_->peersForConversation(conversation); + if (peers.empty()) { + // Should not + qDebug() << "ConversationModel::removeConversation can't remove a conversation without " + "participant"; + return; + } + if (conversation.isSwarm()) { + if (conversation.isRequest) + ConfigurationManager::instance().declineConversationRequest(owner.id, uid); + else + ConfigurationManager::instance().removeConversation(owner.id, uid); + + // Still some other conversation, do nothing else + if (!banned && getConversationForPeerUri(peers.front()) != std::nullopt) + return; + } + + if (!conversation.isCoreDialog()) + return; + owner.contactModel->removeContact(peers.front(), banned); +} + +void +ConversationModel::deleteObsoleteHistory(int days) +{ + if (days < 1) + return; // unlimited history + + auto currentTime = static_cast<long int>(std::time(nullptr)); // since epoch, in seconds... + auto date = currentTime - (days * 86400); + + storage::deleteObsoleteHistory(pimpl_->db, date); +} + +void +ConversationModelPimpl::placeCall(const QString& uid, bool isAudioOnly) +{ + try { + auto& conversation = getConversationForUid(uid, true).get(); + if (conversation.participants.empty()) { + // Should not + qDebug() + << "ConversationModel::placeCall can't call a conversation without participant"; + return; + } + auto& peers = peersForConversation(conversation); + // there is no calls in group with more than 2 participants + if (peers.size() != 1) { + return; + } + // Disallow multiple call + if (!conversation.callId.isEmpty()) { + try { + auto call = linked.owner.callModel->getCall(conversation.callId); + switch (call.status) { + case call::Status::INCOMING_RINGING: + case call::Status::OUTGOING_RINGING: + case call::Status::CONNECTING: + case call::Status::SEARCHING: + case call::Status::PAUSED: + case call::Status::IN_PROGRESS: + case call::Status::CONNECTED: + return; + case call::Status::INVALID: + case call::Status::INACTIVE: + case call::Status::ENDED: + case call::Status::PEER_BUSY: + case call::Status::TIMEOUT: + case call::Status::TERMINATING: + default: + break; + } + } catch (const std::out_of_range&) { + } + } + + auto convId = uid; + + auto participant = peers.front(); + bool isTemporary = participant == convId; + auto contactInfo = linked.owner.contactModel->getContact(participant); + auto uri = contactInfo.profileInfo.uri; + + if (uri.isEmpty()) + return; // Incorrect item + + // Don't call banned contact + if (contactInfo.isBanned) { + qDebug() << "ContactModel::placeCall: denied, contact is banned"; + return; + } + + if (linked.owner.profileInfo.type != profile::Type::SIP) { + uri = "ring:" + uri; // Add the ring: before or it will fail. + } + + auto cb = ([this, isTemporary, uri, isAudioOnly, &conversation](QString conversationId) { + if (indexOf(conversationId) < 0) { + qDebug() << "Can't place call: conversation not exists"; + return; + } + + auto& newConv = isTemporary ? getConversationForUid(conversationId).get() + : conversation; + + newConv.callId = linked.owner.callModel->createCall(uri, isAudioOnly); + if (newConv.callId.isEmpty()) { + qDebug() << "Can't place call (daemon side failure ?)"; + return; + } + + invalidateModel(); + + Q_EMIT behaviorController.showIncomingCallView(linked.owner.id, newConv.uid); + }); + + if (isTemporary) { + QMetaObject::Connection* const connection = new QMetaObject::Connection; + *connection = connect(&this->linked, + &ConversationModel::conversationReady, + [cb, connection, convId](QString conversationId, + QString participantId) { + if (participantId != convId) { + return; + } + cb(conversationId); + QObject::disconnect(*connection); + if (connection) { + delete connection; + } + }); + } + + sendContactRequest(participant); + + if (!isTemporary) { + cb(convId); + } + } catch (const std::out_of_range& e) { + qDebug() << "could not place call to not existing conversation"; + } +} + +void +ConversationModel::placeAudioOnlyCall(const QString& uid) +{ + pimpl_->placeCall(uid, true); +} + +void +ConversationModel::placeCall(const QString& uid) +{ + pimpl_->placeCall(uid); +} + +MapStringString +ConversationModel::getConversationInfos(const QString& conversationId) +{ + MapStringString ret = ConfigurationManager::instance().conversationInfos(owner.id, + conversationId); + return ret; +} + +void +ConversationModel::createConversation(const VectorString& participants, const MapStringString& infos) +{ + auto convUid = ConfigurationManager::instance().startConversation(owner.id); + for (const auto& participant : participants) { + ConfigurationManager::instance().addConversationMember(owner.id, convUid, participant); + } + if (!infos.isEmpty()) + updateConversationInfos(convUid, infos); + pimpl_->addSwarmConversation(convUid); + Q_EMIT newConversation(convUid); + pimpl_->invalidateModel(); + Q_EMIT modelChanged(); +} + +void +ConversationModel::updateConversationInfos(const QString& conversationId, const MapStringString info) +{ + ConfigurationManager::instance().updateConversationInfos(owner.id, conversationId, info); +} + +bool +ConversationModel::hasPendingRequests() const +{ + return pendingRequestCount() > 0; +} + +int +ConversationModel::pendingRequestCount() const +{ + int pendingRequestCount = 0; + std::for_each(pimpl_->conversations.begin(), + pimpl_->conversations.end(), + [&pendingRequestCount](const auto& c) { pendingRequestCount += c.isRequest; }); + return pendingRequestCount; +} + +int +ConversationModel::notificationsCount() const +{ + int notificationsCount = 0; + std::for_each(pimpl_->conversations.begin(), + pimpl_->conversations.end(), + [¬ificationsCount](const auto& c) { + if (c.isRequest) + notificationsCount += 1; + else { + notificationsCount += c.unreadMessages; + } + }); + return notificationsCount; +} + +QString +ConversationModel::title(const QString& conversationId) const +{ + auto conversationOpt = getConversationForUid(conversationId); + if (!conversationOpt.has_value()) { + return {}; + } + auto& conversation = conversationOpt->get(); + if (conversation.isCoreDialog()) { + auto peer = pimpl_->peersForConversation(conversation); + if (peer.isEmpty()) + return {}; + // In this case, we can just display contact name + return owner.contactModel->bestNameForContact(peer.at(0)); + } + if (conversation.infos["title"] != "") { + return conversation.infos["title"]; + } + // NOTE: Do not call any daemon method there as title() is called a lot for drawing + QString title; + auto idx = 0u; + auto others = 0; + for (const auto& member : conversation.participants) { + QString name; + if (member.uri == owner.profileInfo.uri) { + name = owner.accountModel->bestNameForAccount(owner.id); + } else { + name = owner.contactModel->bestNameForContact(member.uri); + } + if (title.length() + name.length() > 32) { + // Avoid too long titles + others += 1; + continue; + } + title += name; + idx += 1; + if (idx != conversation.participants.size() || others != 0) { + title += ", "; + } + } + if (others != 0) { + title += QString("+ %1").arg(others); + } + return title; +} + +member::Role +ConversationModel::memberRole(const QString& conversationId, const QString& memberUri) const +{ + auto conversationOpt = getConversationForUid(conversationId); + if (!conversationOpt.has_value()) + throw std::out_of_range("Member out of range"); + auto& conversation = conversationOpt->get(); + for (const auto& p : conversation.participants) { + if (p.uri == memberUri) + return p.role; + } + throw std::out_of_range("Member out of range"); +} + +QString +ConversationModel::description(const QString& conversationId) const +{ + auto conversationOpt = getConversationForUid(conversationId); + if (!conversationOpt.has_value()) { + return {}; + } + auto& conversation = conversationOpt->get(); + return conversation.infos["description"]; +} + +QString +ConversationModel::avatar(const QString& conversationId) const +{ + auto conversationOpt = getConversationForUid(conversationId); + if (!conversationOpt.has_value()) { + return {}; + } + auto& conversation = conversationOpt->get(); + if (conversation.isCoreDialog()) { + auto peer = pimpl_->peersForConversation(conversation); + if (peer.isEmpty()) + return {}; + // In this case, we can just display contact name + return owner.contactModel->avatar(peer.at(0)); + } + return conversation.infos["avatar"]; +} + +void +ConversationModel::sendMessage(const QString& uid, const QString& body, const QString& parentId) +{ + try { + auto& conversation = pimpl_->getConversationForUid(uid, true).get(); + if (!conversation.isLegacy()) { + ConfigurationManager::instance().sendMessage(owner.id, uid, body, parentId); + return; + } + + auto& peers = pimpl_->peersForConversation(conversation); + if (peers.isEmpty()) { + // Should not + qDebug() << "ConversationModel::sendMessage can't send a interaction to a conversation " + "with no participant"; + return; + } + auto convId = uid; + auto& peerId = peers.front(); + bool isTemporary = peerId == convId; + + auto cb = ([this, isTemporary, body, &conversation, parentId, convId]( + QString conversationId) { + if (pimpl_->indexOf(conversationId) < 0) { + return; + } + auto& newConv = isTemporary ? pimpl_->getConversationForUid(conversationId).get() + : conversation; + + if (newConv.isSwarm()) { + ConfigurationManager::instance().sendMessage(owner.id, + conversationId, + body, + parentId); + return; + } + auto& peers = pimpl_->peersForConversation(newConv); + if (peers.isEmpty()) { + return; + } + + uint64_t daemonMsgId = 0; + auto status = interaction::Status::SENDING; + auto convId = newConv.uid; + + QStringList callLists = CallManager::instance().getCallList(""); // no auto + // workaround: sometimes, it may happen that the daemon delete a call, but lrc + // don't. We check if the call is + // still valid every time the user want to send a message. + if (not newConv.callId.isEmpty() and not callLists.contains(newConv.callId)) + newConv.callId.clear(); + + if (not newConv.callId.isEmpty() + and call::canSendSIPMessage(owner.callModel->getCall(newConv.callId))) { + status = interaction::Status::UNKNOWN; + owner.callModel->sendSipMessage(newConv.callId, body); + + } else { + daemonMsgId = owner.contactModel->sendDhtMessage(peers.front(), body); + } + + // Add interaction to database + interaction::Info + msg {{}, body, std::time(nullptr), 0, interaction::Type::TEXT, status, true}; + auto msgId = storage::addMessageToConversation(pimpl_->db, convId, msg); + + // Update conversation + if (status == interaction::Status::SENDING) { + // Because the daemon already give an id for the message, we need to store it. + storage::addDaemonMsgId(pimpl_->db, msgId, toQString(daemonMsgId)); + } + + bool ret = false; + + { + std::lock_guard<std::mutex> lk(pimpl_->interactionsLocks[convId]); + ret = newConv.interactions->insert(std::pair<QString, interaction::Info>(msgId, msg)) + .second; + } + + if (!ret) { + qDebug() + << "ConversationModel::sendMessage failed to send message because an existing " + "key was already present in the database key =" + << msgId; + return; + } + + newConv.lastMessageUid = msgId; + // Emit this signal for chatview in the client + Q_EMIT newInteraction(convId, msgId, msg); + // This conversation is now at the top of the list + // The order has changed, informs the client to redraw the list + pimpl_->invalidateModel(); + Q_EMIT modelChanged(); + Q_EMIT dataChanged(pimpl_->indexOf(convId)); + }); + + if (isTemporary) { + QMetaObject::Connection* const connection = new QMetaObject::Connection; + *connection = connect(this, + &ConversationModel::conversationReady, + [cb, connection, convId](QString conversationId, + QString participantId) { + if (participantId != convId) { + return; + } + cb(conversationId); + QObject::disconnect(*connection); + if (connection) { + delete connection; + } + }); + } + pimpl_->sendContactRequest(peerId); + if (!isTemporary) { + cb(convId); + } + } catch (const std::out_of_range& e) { + qDebug() << "could not send message to not existing conversation"; + } +} + +void +ConversationModel::refreshFilter() +{ + pimpl_->invalidateModel(); + Q_EMIT filterChanged(); +} + +void +ConversationModel::updateSearchStatus(const QString& status) const +{ + Q_EMIT searchStatusChanged(status); +} + +void +ConversationModel::setFilter(const QString& filter) +{ + pimpl_->currentFilter = filter; + pimpl_->invalidateModel(); + pimpl_->searchResults.clear(); + Q_EMIT searchResultUpdated(); + owner.contactModel->searchContact(filter); + Q_EMIT filterChanged(); +} + +void +ConversationModel::setFilter(const FilterType& filter) +{ + // Switch between PENDING, RING and SIP contacts. + pimpl_->typeFilter = filter; + pimpl_->invalidateModel(); + Q_EMIT filterChanged(); +} + +void +ConversationModel::joinConversations(const QString& uidA, const QString& uidB) +{ + auto conversationAIdx = pimpl_->indexOf(uidA); + auto conversationBIdx = pimpl_->indexOf(uidB); + if (conversationAIdx == -1 || conversationBIdx == -1 || !owner.enabled) + return; + auto& conversationA = pimpl_->conversations[conversationAIdx]; + auto& conversationB = pimpl_->conversations[conversationBIdx]; + + if (conversationA.callId.isEmpty() || conversationB.callId.isEmpty()) + return; + + if (conversationA.confId.isEmpty()) { + if (conversationB.confId.isEmpty()) { + owner.callModel->joinCalls(conversationA.callId, conversationB.callId); + } else { + owner.callModel->joinCalls(conversationA.callId, conversationB.confId); + conversationA.confId = conversationB.confId; + } + } else { + if (conversationB.confId.isEmpty()) { + owner.callModel->joinCalls(conversationA.confId, conversationB.callId); + conversationB.confId = conversationA.confId; + } else { + owner.callModel->joinCalls(conversationA.confId, conversationB.confId); + conversationB.confId = conversationA.confId; + } + } +} + +void +ConversationModel::clearHistory(const QString& uid) +{ + auto conversationIdx = pimpl_->indexOf(uid); + if (conversationIdx == -1) + return; + + auto& conversation = pimpl_->conversations.at(conversationIdx); + // Remove all TEXT interactions from database + storage::clearHistory(pimpl_->db, uid); + // Update conversation + { + std::lock_guard<std::mutex> lk(pimpl_->interactionsLocks[uid]); + conversation.interactions->clear(); + } + storage::getHistory(pimpl_->db, conversation); // will contain "Conversation started" + + Q_EMIT modelChanged(); + Q_EMIT conversationCleared(uid); + Q_EMIT dataChanged(conversationIdx); +} + +void +ConversationModel::clearInteractionFromConversation(const QString& convId, + const QString& interactionId) +{ + auto conversationIdx = pimpl_->indexOf(convId); + if (conversationIdx == -1) + return; + + auto erased_keys = 0; + bool lastInteractionUpdated = false; + bool updateDisplayedUid = false; + QString newDisplayedUid = 0; + QString participantURI = ""; + { + std::lock_guard<std::mutex> lk(pimpl_->interactionsLocks[convId]); + try { + auto& conversation = pimpl_->conversations.at(conversationIdx); + if (conversation.isSwarm()) { + // WARNING: clearInteractionFromConversation not implemented for swarm + return; + } + storage::clearInteractionFromConversation(pimpl_->db, convId, interactionId); + erased_keys = conversation.interactions->erase(interactionId); + participantURI = pimpl_->peersForConversation(conversation).front(); + auto messageId = conversation.interactions->getRead(participantURI); + + if (messageId != "" && messageId == interactionId) { + for (auto iter = conversation.interactions->find(interactionId); + iter != conversation.interactions->end(); + --iter) { + if (isOutgoing(iter->second) && iter->first != interactionId) { + newDisplayedUid = iter->first; + break; + } + } + updateDisplayedUid = true; + conversation.interactions->setRead(participantURI, newDisplayedUid); + } + + if (conversation.lastMessageUid == interactionId) { + // Update lastMessageUid + auto newLastId = QString::number(0); + if (!conversation.interactions->empty()) + newLastId = conversation.interactions->rbegin()->first; + conversation.lastMessageUid = newLastId; + lastInteractionUpdated = true; + } + + } catch (const std::out_of_range& e) { + qDebug() << "can't clear interaction from conversation: " << e.what(); + } + } + if (updateDisplayedUid) { + Q_EMIT displayedInteractionChanged(convId, participantURI, interactionId, newDisplayedUid); + } + if (erased_keys > 0) { + pimpl_->filteredConversations.invalidate(); + Q_EMIT interactionRemoved(convId, interactionId); + } + if (lastInteractionUpdated) { + // last interaction as changed, so the order can change. + Q_EMIT modelChanged(); + Q_EMIT dataChanged(conversationIdx); + } +} + +void +ConversationModel::clearInteractionsCache(const QString& convId) +{ + auto conversationIdx = pimpl_->indexOf(convId); + if (conversationIdx == -1) + return; + + try { + auto& conversation = pimpl_->conversations.at(conversationIdx); + if (!conversation.isRequest && !conversation.needsSyncing && conversation.isSwarm()) { + { + std::lock_guard<std::mutex> lk(pimpl_->interactionsLocks[convId]); + conversation.interactions->clear(); + } + conversation.allMessagesLoaded = false; + conversation.lastMessageUid = ""; + ConfigurationManager::instance().loadConversationMessages(owner.id, convId, "", 1); + } + } catch (const std::out_of_range& e) { + qDebug() << "can't find interaction from conversation: " << e.what(); + return; + } +} + +void +ConversationModel::retryInteraction(const QString& convId, const QString& interactionId) +{ + auto conversationIdx = pimpl_->indexOf(convId); + if (conversationIdx == -1) + return; + + auto interactionType = interaction::Type::INVALID; + QString body = {}; + { + std::lock_guard<std::mutex> lk(pimpl_->interactionsLocks[convId]); + try { + auto& conversation = pimpl_->conversations.at(conversationIdx); + if (conversation.isSwarm()) { + // WARNING: retry interaction is not implemented for swarm + return; + } + + auto& interactions = conversation.interactions; + auto it = interactions->find(interactionId); + if (it == interactions->end()) + return; + + if (!interaction::isOutgoing(it->second)) + return; // Do not retry non outgoing info + + if (it->second.type == interaction::Type::TEXT + || (it->second.type == interaction::Type::DATA_TRANSFER + && interaction::isOutgoing(it->second))) { + body = it->second.body; + interactionType = it->second.type; + } else + return; + + storage::clearInteractionFromConversation(pimpl_->db, convId, interactionId); + conversation.interactions->erase(interactionId); + } catch (const std::out_of_range& e) { + qDebug() << "can't find interaction from conversation: " << e.what(); + return; + } + } + Q_EMIT interactionRemoved(convId, interactionId); + + // Send a new interaction like the previous one + if (interactionType == interaction::Type::TEXT) { + sendMessage(convId, body); + } else { + // send file + QFileInfo f(body); + sendFile(convId, body, f.fileName()); + } +} + +bool +ConversationModel::isLastDisplayed(const QString& convId, + const QString& interactionId, + const QString participant) +{ + auto conversationIdx = pimpl_->indexOf(convId); + try { + auto& conversation = pimpl_->conversations.at(conversationIdx); + return conversation.interactions->getRead(participant) == interactionId; + } catch (const std::out_of_range& e) { + } + return false; +} + +void +ConversationModel::clearAllHistory() +{ + storage::clearAllHistory(pimpl_->db); + + for (auto& conversation : pimpl_->conversations) { + { + if (conversation.isSwarm()) { + // WARNING: clear all history is not implemented for swarm + continue; + } + std::lock_guard<std::mutex> lk(pimpl_->interactionsLocks[conversation.uid]); + conversation.interactions->clear(); + } + storage::getHistory(pimpl_->db, conversation); + Q_EMIT dataChanged(pimpl_->indexOf(conversation.uid)); + } + Q_EMIT modelChanged(); +} + +void +ConversationModel::setInteractionRead(const QString& convId, const QString& interactionId) +{ + auto conversationIdx = pimpl_->indexOf(convId); + if (conversationIdx == -1) { + return; + } + bool emitUpdated = false; + interaction::Info itCopy; + { + std::lock_guard<std::mutex> lk(pimpl_->interactionsLocks[convId]); + auto& interactions = pimpl_->conversations[conversationIdx].interactions; + auto it = interactions->find(interactionId); + if (it != interactions->end()) { + emitUpdated = true; + if (it->second.isRead) { + return; + } + it->second.isRead = true; + interactions->emitDataChanged(it, {MessageList::Role::IsRead}); + if (pimpl_->conversations[conversationIdx].unreadMessages != 0) + pimpl_->conversations[conversationIdx].unreadMessages -= 1; + itCopy = it->second; + } + } + if (emitUpdated) { + pimpl_->invalidateModel(); + if (pimpl_->conversations[conversationIdx].isSwarm()) { + ConfigurationManager::instance().setMessageDisplayed(owner.id, + "swarm:" + convId, + interactionId, + 3); + } else { + auto daemonId = storage::getDaemonIdByInteractionId(pimpl_->db, interactionId); + if (owner.profileInfo.type != profile::Type::SIP) { + ConfigurationManager::instance() + .setMessageDisplayed(owner.id, + "jami:" + + pimpl_ + ->peersForConversation( + pimpl_->conversations[conversationIdx]) + .front(), + daemonId, + 3); + } + storage::setInteractionRead(pimpl_->db, interactionId); + } + Q_EMIT interactionStatusUpdated(convId, interactionId, itCopy); + Q_EMIT pimpl_->behaviorController.newReadInteraction(owner.id, convId, interactionId); + } +} + +void +ConversationModel::clearUnreadInteractions(const QString& convId) +{ + auto conversationOpt = getConversationForUid(convId); + if (!conversationOpt.has_value()) { + return; + } + auto& conversation = conversationOpt->get(); + bool emitUpdated = false; + QString lastDisplayed; + { + std::lock_guard<std::mutex> lk(pimpl_->interactionsLocks[convId]); + auto& interactions = conversation.interactions; + if (conversation.isSwarm()) { + emitUpdated = true; + if (!interactions->empty()) + lastDisplayed = interactions->rbegin()->first; + } else { + std::for_each(interactions->begin(), + interactions->end(), + [&](decltype(*interactions->begin())& it) { + if (!it.second.isRead) { + emitUpdated = true; + it.second.isRead = true; + if (owner.profileInfo.type != profile::Type::SIP) + lastDisplayed = storage::getDaemonIdByInteractionId(pimpl_->db, + it.first); + storage::setInteractionRead(pimpl_->db, it.first); + } + }); + } + } + if (!lastDisplayed.isEmpty()) { + auto to = conversation.isSwarm() + ? "swarm:" + convId + : "jami:" + pimpl_->peersForConversation(conversation).front(); + ConfigurationManager::instance().setMessageDisplayed(owner.id, to, lastDisplayed, 3); + } + if (emitUpdated) { + conversation.unreadMessages = 0; + pimpl_->invalidateModel(); + Q_EMIT conversationUpdated(convId); + Q_EMIT dataChanged(pimpl_->indexOf(convId)); + } +} + +int +ConversationModel::loadConversationMessages(const QString& conversationId, const int size) +{ + auto conversationOpt = getConversationForUid(conversationId); + if (!conversationOpt.has_value()) { + return -1; + } + auto& conversation = conversationOpt->get(); + if (conversation.allMessagesLoaded) { + return -1; + } + auto lastMsgId = conversation.interactions->empty() ? "" + : conversation.interactions->front().first; + return ConfigurationManager::instance().loadConversationMessages(owner.id, + conversationId, + lastMsgId, + size); +} + +void +ConversationModel::acceptConversationRequest(const QString& conversationId) +{ + auto conversationOpt = getConversationForUid(conversationId); + if (!conversationOpt.has_value()) { + return; + } + auto& conversation = conversationOpt->get(); + auto& peers = pimpl_->peersForConversation(conversation); + if (peers.isEmpty()) { + return; + } + switch (conversation.mode) { + case conversation::Mode::NON_SWARM: + pimpl_->sendContactRequest(peers.front()); + return; + case conversation::Mode::ONE_TO_ONE: { + // add contact if not added. Otherwise, accept the conversation request + try { + auto contact = owner.contactModel->getContact(peers.front()); + auto notAdded = contact.profileInfo.type == profile::Type::TEMPORARY + || contact.profileInfo.type == profile::Type::PENDING; + if (notAdded) { + owner.contactModel->addContact(contact); + return; + } + } catch (std::out_of_range& e) { + } + break; + } + case conversation::Mode::ADMIN_INVITES_ONLY: + case conversation::Mode::INVITES_ONLY: + case conversation::Mode::PUBLIC: + default: + break; + } + conversation.needsSyncing = true; + Q_EMIT conversationUpdated(conversation.uid); + pimpl_->invalidateModel(); + Q_EMIT modelChanged(); + ConfigurationManager::instance().acceptConversationRequest(owner.id, conversationId); +} + +const VectorString +ConversationModel::peersForConversation(const QString& conversationId) +{ + const auto conversationOpt = getConversationForUid(conversationId); + if (!conversationOpt.has_value()) { + return {}; + } + const auto& conversation = conversationOpt->get(); + return pimpl_->peersForConversation(conversation); +} + +void +ConversationModel::addConversationMember(const QString& conversationId, const QString& memberId) +{ + ConfigurationManager::instance().addConversationMember(owner.id, conversationId, memberId); +} + +void +ConversationModel::removeConversationMember(const QString& conversationId, const QString& memberId) +{ + ConfigurationManager::instance().removeConversationMember(owner.id, conversationId, memberId); +} + +ConversationModelPimpl::ConversationModelPimpl(const ConversationModel& linked, + Lrc& lrc, + Database& db, + const CallbacksHandler& callbacksHandler, + const BehaviorController& behaviorController) + : linked(linked) + , lrc {lrc} + , db(db) + , callbacksHandler(callbacksHandler) + , typeFilter(FilterType::INVALID) + , customTypeFilter(FilterType::INVALID) + , behaviorController(behaviorController) +{ + filteredConversations.bindSortCallback(this, &ConversationModelPimpl::sort); + filteredConversations.bindFilterCallback(this, &ConversationModelPimpl::filter); + + initConversations(); + + // Contact related + connect(&*linked.owner.contactModel, + &ContactModel::modelUpdated, + this, + &ConversationModelPimpl::slotContactModelUpdated); + connect(&*linked.owner.contactModel, + &ContactModel::contactAdded, + this, + &ConversationModelPimpl::slotContactAdded); + connect(&*linked.owner.contactModel, + &ContactModel::incomingContactRequest, + this, + &ConversationModelPimpl::slotIncomingContactRequest); + connect(&*linked.owner.contactModel, + &ContactModel::pendingContactAccepted, + this, + &ConversationModelPimpl::slotPendingContactAccepted); + connect(&*linked.owner.contactModel, + &ContactModel::contactRemoved, + this, + &ConversationModelPimpl::slotContactRemoved); + + // Messages related + connect(&*linked.owner.contactModel, + &lrc::ContactModel::newAccountMessage, + this, + &ConversationModelPimpl::slotNewAccountMessage); + connect(&callbacksHandler, + &CallbacksHandler::incomingCallMessage, + this, + &ConversationModelPimpl::slotIncomingCallMessage); + connect(&callbacksHandler, + &CallbacksHandler::accountMessageStatusChanged, + this, + &ConversationModelPimpl::slotUpdateInteractionStatus); + + // Call related + connect(&*linked.owner.contactModel, + &ContactModel::incomingCall, + this, + &ConversationModelPimpl::slotIncomingCall); + connect(&*linked.owner.callModel, + &lrc::api::NewCallModel::callStatusChanged, + this, + &ConversationModelPimpl::slotCallStatusChanged); + connect(&*linked.owner.callModel, + &lrc::api::NewCallModel::callStarted, + this, + &ConversationModelPimpl::slotCallStarted); + connect(&*linked.owner.callModel, + &lrc::api::NewCallModel::callEnded, + this, + &ConversationModelPimpl::slotCallEnded); + connect(&*linked.owner.callModel, + &lrc::api::NewCallModel::callAddedToConference, + this, + &ConversationModelPimpl::slotCallAddedToConference); + connect(&callbacksHandler, + &CallbacksHandler::conferenceRemoved, + this, + &ConversationModelPimpl::slotConferenceRemoved); + connect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::composingStatusChanged, + this, + &ConversationModelPimpl::slotComposingStatusChanged); + + // data transfer + connect(&*linked.owner.contactModel, + &ContactModel::newAccountTransfer, + this, + &ConversationModelPimpl::slotTransferStatusCreated); + connect(&callbacksHandler, + &CallbacksHandler::transferStatusCanceled, + this, + &ConversationModelPimpl::slotTransferStatusCanceled); + connect(&callbacksHandler, + &CallbacksHandler::transferStatusAwaitingPeer, + this, + &ConversationModelPimpl::slotTransferStatusAwaitingPeer); + connect(&callbacksHandler, + &CallbacksHandler::transferStatusAwaitingHost, + this, + &ConversationModelPimpl::slotTransferStatusAwaitingHost); + connect(&callbacksHandler, + &CallbacksHandler::transferStatusOngoing, + this, + &ConversationModelPimpl::slotTransferStatusOngoing); + connect(&callbacksHandler, + &CallbacksHandler::transferStatusFinished, + this, + &ConversationModelPimpl::slotTransferStatusFinished); + connect(&callbacksHandler, + &CallbacksHandler::transferStatusError, + this, + &ConversationModelPimpl::slotTransferStatusError); + connect(&callbacksHandler, + &CallbacksHandler::transferStatusTimeoutExpired, + this, + &ConversationModelPimpl::slotTransferStatusTimeoutExpired); + connect(&callbacksHandler, + &CallbacksHandler::transferStatusUnjoinable, + this, + &ConversationModelPimpl::slotTransferStatusUnjoinable); + // swarm conversations + connect(&callbacksHandler, + &CallbacksHandler::conversationLoaded, + this, + &ConversationModelPimpl::slotConversationLoaded); + connect(&callbacksHandler, + &CallbacksHandler::messageReceived, + this, + &ConversationModelPimpl::slotMessageReceived); + connect(&callbacksHandler, + &CallbacksHandler::conversationRequestReceived, + this, + &ConversationModelPimpl::slotConversationRequestReceived); + connect(&callbacksHandler, + &CallbacksHandler::conversationRequestDeclined, + this, + &ConversationModelPimpl::slotConversationRequestDeclined); + connect(&callbacksHandler, + &CallbacksHandler::conversationReady, + this, + &ConversationModelPimpl::slotConversationReady); + connect(&callbacksHandler, + &CallbacksHandler::conversationRemoved, + this, + &ConversationModelPimpl::slotConversationRemoved); + connect(&callbacksHandler, + &CallbacksHandler::conversationMemberEvent, + this, + &ConversationModelPimpl::slotConversationMemberEvent); +} + +ConversationModelPimpl::~ConversationModelPimpl() +{ + // Contact related + disconnect(&*linked.owner.contactModel, + &ContactModel::modelUpdated, + this, + &ConversationModelPimpl::slotContactModelUpdated); + disconnect(&*linked.owner.contactModel, + &ContactModel::contactAdded, + this, + &ConversationModelPimpl::slotContactAdded); + disconnect(&*linked.owner.contactModel, + &ContactModel::incomingContactRequest, + this, + &ConversationModelPimpl::slotIncomingContactRequest); + disconnect(&*linked.owner.contactModel, + &ContactModel::pendingContactAccepted, + this, + &ConversationModelPimpl::slotPendingContactAccepted); + disconnect(&*linked.owner.contactModel, + &ContactModel::contactRemoved, + this, + &ConversationModelPimpl::slotContactRemoved); + + // Messages related + disconnect(&*linked.owner.contactModel, + &lrc::ContactModel::newAccountMessage, + this, + &ConversationModelPimpl::slotNewAccountMessage); + disconnect(&callbacksHandler, + &CallbacksHandler::incomingCallMessage, + this, + &ConversationModelPimpl::slotIncomingCallMessage); + disconnect(&callbacksHandler, + &CallbacksHandler::accountMessageStatusChanged, + this, + &ConversationModelPimpl::slotUpdateInteractionStatus); + + // Call related + disconnect(&*linked.owner.contactModel, + &ContactModel::incomingCall, + this, + &ConversationModelPimpl::slotIncomingCall); + disconnect(&*linked.owner.callModel, + &lrc::api::NewCallModel::callStatusChanged, + this, + &ConversationModelPimpl::slotCallStatusChanged); + disconnect(&*linked.owner.callModel, + &lrc::api::NewCallModel::callStarted, + this, + &ConversationModelPimpl::slotCallStarted); + disconnect(&*linked.owner.callModel, + &lrc::api::NewCallModel::callEnded, + this, + &ConversationModelPimpl::slotCallEnded); + disconnect(&*linked.owner.callModel, + &lrc::api::NewCallModel::callAddedToConference, + this, + &ConversationModelPimpl::slotCallAddedToConference); + disconnect(&callbacksHandler, + &CallbacksHandler::conferenceRemoved, + this, + &ConversationModelPimpl::slotConferenceRemoved); + disconnect(&ConfigurationManager::instance(), + &ConfigurationManagerInterface::composingStatusChanged, + this, + &ConversationModelPimpl::slotComposingStatusChanged); + + // data transfer + disconnect(&*linked.owner.contactModel, + &ContactModel::newAccountTransfer, + this, + &ConversationModelPimpl::slotTransferStatusCreated); + disconnect(&callbacksHandler, + &CallbacksHandler::transferStatusCanceled, + this, + &ConversationModelPimpl::slotTransferStatusCanceled); + disconnect(&callbacksHandler, + &CallbacksHandler::transferStatusAwaitingPeer, + this, + &ConversationModelPimpl::slotTransferStatusAwaitingPeer); + disconnect(&callbacksHandler, + &CallbacksHandler::transferStatusAwaitingHost, + this, + &ConversationModelPimpl::slotTransferStatusAwaitingHost); + disconnect(&callbacksHandler, + &CallbacksHandler::transferStatusOngoing, + this, + &ConversationModelPimpl::slotTransferStatusOngoing); + disconnect(&callbacksHandler, + &CallbacksHandler::transferStatusFinished, + this, + &ConversationModelPimpl::slotTransferStatusFinished); + disconnect(&callbacksHandler, + &CallbacksHandler::transferStatusError, + this, + &ConversationModelPimpl::slotTransferStatusError); + disconnect(&callbacksHandler, + &CallbacksHandler::transferStatusTimeoutExpired, + this, + &ConversationModelPimpl::slotTransferStatusTimeoutExpired); + disconnect(&callbacksHandler, + &CallbacksHandler::transferStatusUnjoinable, + this, + &ConversationModelPimpl::slotTransferStatusUnjoinable); + // swarm conversations + disconnect(&callbacksHandler, + &CallbacksHandler::conversationLoaded, + this, + &ConversationModelPimpl::slotConversationLoaded); + disconnect(&callbacksHandler, + &CallbacksHandler::messageReceived, + this, + &ConversationModelPimpl::slotMessageReceived); + disconnect(&callbacksHandler, + &CallbacksHandler::conversationRequestReceived, + this, + &ConversationModelPimpl::slotConversationRequestReceived); + disconnect(&callbacksHandler, + &CallbacksHandler::conversationRequestDeclined, + this, + &ConversationModelPimpl::slotConversationRequestDeclined); + disconnect(&callbacksHandler, + &CallbacksHandler::conversationReady, + this, + &ConversationModelPimpl::slotConversationReady); + disconnect(&callbacksHandler, + &CallbacksHandler::conversationRemoved, + this, + &ConversationModelPimpl::slotConversationRemoved); + disconnect(&callbacksHandler, + &CallbacksHandler::conversationMemberEvent, + this, + &ConversationModelPimpl::slotConversationMemberEvent); +} + +void +ConversationModelPimpl::initConversations() +{ + const MapStringString accountDetails = ConfigurationManager::instance().getAccountDetails( + linked.owner.id); + if (accountDetails.empty()) + return; + + // Fill swarm conversations + QStringList swarms = ConfigurationManager::instance().getConversations(linked.owner.id); + for (auto& swarmConv : swarms) { + addSwarmConversation(swarmConv); + } + + VectorMapStringString conversationsRequests = ConfigurationManager::instance() + .getConversationRequests(linked.owner.id); + for (auto& request : conversationsRequests) { + addConversationRequest(request); + } + + // Fill conversations + for (auto const& c : linked.owner.contactModel->getAllContacts().toStdMap()) { + auto conv = storage::getConversationsWithPeer(db, c.second.profileInfo.uri); + if (hasOneOneSwarmWith(c.second.profileInfo.uri)) + continue; + bool isRequest = c.second.profileInfo.type == profile::Type::PENDING; + if (conv.empty()) { + // Can't find a conversation with this contact + // add pending not swarm conversation + if (isRequest) { + addContactRequest(c.second.profileInfo.uri); + continue; + } + conv.push_back(storage::beginConversationWithPeer(db, + c.second.profileInfo.uri, + true, + linked.owner.contactModel->getAddedTs( + c.second.profileInfo.uri))); + } + addConversationWith(conv[0], c.first, isRequest); + + auto convIdx = indexOf(conv[0]); + + // Check if file transfer interactions were left in an incorrect state + std::lock_guard<std::mutex> lk(interactionsLocks[conversations[convIdx].uid]); + for (auto& interaction : *(conversations[convIdx].interactions)) { + if (interaction.second.status == interaction::Status::TRANSFER_CREATED + || interaction.second.status == interaction::Status::TRANSFER_AWAITING_HOST + || interaction.second.status == interaction::Status::TRANSFER_AWAITING_PEER + || interaction.second.status == interaction::Status::TRANSFER_ONGOING + || interaction.second.status == interaction::Status::TRANSFER_ACCEPTED) { + // If a datatransfer was left in a non-terminal status in DB, we switch this status + // to ERROR + // TODO : Improve for DBus clients as daemon and transfer may still be ongoing + storage::updateInteractionStatus(db, + interaction.first, + interaction::Status::TRANSFER_ERROR); + interaction.second.status = interaction::Status::TRANSFER_ERROR; + } + } + } + invalidateModel(); + + filteredConversations.reset(conversations).sort(); + + // Load all non treated messages for this account + QVector<Message> messages = ConfigurationManager::instance() + .getLastMessages(linked.owner.id, storage::getLastTimestamp(db)); + for (const auto& message : messages) { + uint64_t timestamp = 0; + try { + timestamp = static_cast<uint64_t>(message.received); + } catch (...) { + } + addIncomingMessage(message.from, message.payloads["text/plain"], timestamp); + } +} + +const VectorString +ConversationModelPimpl::peersForConversation(const conversation::Info& conversation) const +{ + VectorString result {}; + switch (conversation.mode) { + case conversation::Mode::NON_SWARM: + return {conversation.participants[0].uri}; + default: + break; + } + // Note: for one to one, we must return self + if (conversation.participants.size() == 1) + return {conversation.participants[0].uri}; + for (const auto& participant : conversation.participants) { + if (participant.uri.isNull()) + continue; + if (participant.uri != linked.owner.profileInfo.uri) + result.push_back(participant.uri); + } + return result; +} + +bool +ConversationModelPimpl::filter(const conversation::Info& entry) +{ + try { + // TODO: filter for group? + // for now group conversation filtered by first peer + auto& peers = peersForConversation(entry); + if (peers.size() < 1) { + return false; + } + auto uriPeer = peers.front(); + contact::Info contactInfo; + try { + contactInfo = linked.owner.contactModel->getContact(uriPeer); + } catch (...) { + // Note: as we search for contacts, when importing a new account, + // the conversation's request can be there without contact, causing + // the function to fail. + contactInfo.profileInfo.uri = uriPeer; + } + + auto uri = URI(currentFilter); + bool stripScheme = (uri.schemeType() < URI::SchemeType::COUNT__); + FlagPack<URI::Section> flags = URI::Section::USER_INFO | URI::Section::HOSTNAME + | URI::Section::PORT; + if (!stripScheme) { + flags |= URI::Section::SCHEME; + } + + currentFilter = uri.format(flags); + + // Check contact + // If contact is banned, only match if filter is a perfect match + // do not check banned contact for conversation with multiple participants + if (contactInfo.isBanned && peers.size() == 1) { + if (currentFilter == "") + return false; + return contactInfo.profileInfo.uri == currentFilter + || contactInfo.profileInfo.alias == currentFilter + || contactInfo.registeredName == currentFilter; + } + + std::regex regexFilter; + auto isValidReFilter = true; + try { + regexFilter = std::regex(currentFilter.toStdString(), std::regex_constants::icase); + } catch (std::regex_error&) { + isValidReFilter = false; + } + + auto filterUriAndReg = [regexFilter, isValidReFilter](auto contact, auto filter) { + auto result = contact.profileInfo.uri.contains(filter) + || contact.registeredName.contains(filter); + if (!result) { + auto regexFound = isValidReFilter + ? (!contact.profileInfo.uri.isEmpty() + && std::regex_search(contact.profileInfo.uri.toStdString(), + regexFilter)) + || std::regex_search(contact.registeredName.toStdString(), + regexFilter) + : false; + result |= regexFound; + } + return result; + }; + + // Check type + switch (typeFilter) { + case FilterType::JAMI: + case FilterType::SIP: + if (entry.isRequest) + return false; + if (contactInfo.profileInfo.type == profile::Type::TEMPORARY) + return filterUriAndReg(contactInfo, currentFilter); + break; + case FilterType::REQUEST: + if (!entry.isRequest) + return false; + break; + default: + break; + } + + // Otherwise perform usual regex search + bool result = contactInfo.profileInfo.alias.contains(currentFilter); + if (!result && isValidReFilter) + result |= std::regex_search(contactInfo.profileInfo.alias.toStdString(), regexFilter); + if (!result) + result |= filterUriAndReg(contactInfo, currentFilter); + return result; + } catch (std::out_of_range&) { + // getContact() failed + return false; + } +} + +bool +ConversationModelPimpl::sort(const conversation::Info& convA, const conversation::Info& convB) +{ + // A or B is a temporary contact + if (convA.participants.isEmpty()) + return true; + if (convB.participants.isEmpty()) + return false; + + if (convA.uid == convB.uid) + return false; + + auto& mtxA = interactionsLocks[convA.uid]; + auto& mtxB = interactionsLocks[convB.uid]; + std::lock(mtxA, mtxB); + std::lock_guard<std::mutex> lockConvA(mtxA, std::adopt_lock); + std::lock_guard<std::mutex> lockConvB(mtxB, std::adopt_lock); + + auto& historyA = convA.interactions; + auto& historyB = convB.interactions; + + // A or B is a new conversation (without CONTACT interaction) + if (convA.uid.isEmpty() || convB.uid.isEmpty()) + return convA.uid.isEmpty(); + + if (historyA->empty() && historyB->empty()) { + // If no information to compare, sort by Ring ID. For group conversation sort by first peer + auto& peersForA = peersForConversation(convA); + auto& peersForB = peersForConversation(convB); + if (peersForA.isEmpty()) { + return false; + } + if (peersForB.isEmpty()) { + return true; + } + return peersForA.front() > peersForB.front(); + } + if (historyA->empty()) + return false; + if (historyB->empty()) + return true; + // Sort by last Interaction + try { + auto lastMessageA = historyA->at(convA.lastMessageUid); + auto lastMessageB = historyB->at(convB.lastMessageUid); + return lastMessageA.timestamp > lastMessageB.timestamp; + } catch (const std::exception& e) { + qDebug() << "ConversationModel::sortConversations(), can't get lastMessage"; + return false; + } +} + +void +ConversationModelPimpl::sendContactRequest(const QString& contactUri) +{ + try { + auto contact = linked.owner.contactModel->getContact(contactUri); + auto isNotUsed = contact.profileInfo.type == profile::Type::TEMPORARY + || contact.profileInfo.type == profile::Type::PENDING; + if (isNotUsed) + linked.owner.contactModel->addContact(contact); + } catch (std::out_of_range& e) { + } +} +void +ConversationModelPimpl::slotConversationLoaded(uint32_t requestId, + const QString& accountId, + const QString& conversationId, + const VectorMapStringString& messages) +{ + if (accountId != linked.owner.id) { + return; + } + + auto allLoaded = false; + + try { + auto& conversation = getConversationForUid(conversationId).get(); + for (const auto& message : messages) { + if (message["type"].isEmpty() || message["type"] == "application/update-profile") { + continue; + } + auto msgId = message["id"]; + auto msg = interaction::Info(message, linked.owner.profileInfo.uri); + auto downloadFile = false; + if (msg.type == interaction::Type::INITIAL) { + allLoaded = true; + } else if (msg.type == interaction::Type::DATA_TRANSFER) { + auto fileId = message["fileId"]; + QString path; + qlonglong bytesProgress, totalSize; + linked.owner.dataTransferModel->fileTransferInfo(accountId, + conversationId, + fileId, + path, + totalSize, + bytesProgress); + QFileInfo fi(path); + if (fi.isSymLink()) { + msg.body = fi.symLinkTarget(); + } else { + msg.body = path; + } + msg.status = bytesProgress == 0 ? interaction::Status::TRANSFER_AWAITING_HOST + : bytesProgress == totalSize ? interaction::Status::TRANSFER_FINISHED + : interaction::Status::TRANSFER_ONGOING; + linked.owner.dataTransferModel->registerTransferId(fileId, msgId); + downloadFile = (bytesProgress == 0); + } else if (msg.type == interaction::Type::CALL) { + msg.body = storage::getCallInteractionString(msg.authorUri, msg.duration); + } else if (msg.type == interaction::Type::CONTACT) { + auto bestName = msg.authorUri == linked.owner.profileInfo.uri + ? linked.owner.accountModel->bestNameForAccount(linked.owner.id) + : linked.owner.contactModel->bestNameForContact(msg.authorUri); + msg.body = interaction::getContactInteractionString(bestName, + interaction::to_action( + message["action"])); + } + insertSwarmInteraction(msgId, msg, conversation, true); + if (downloadFile) { + // Note, we must do this after insertSwarmInteraction to find the interaction + handleIncomingFile(conversationId, + msgId, + message["displayName"], + message["totalSize"].toInt()); + } + } + + for (int j = conversation.interactions->size() - 1; j >= 0; j--) { + if (conversation.interactions->atIndex(j).second.type != interaction::Type::MERGE) { + conversation.lastMessageUid = conversation.interactions->atIndex(j).first; + break; + } + } + if (conversation.lastMessageUid.isEmpty() && !conversation.allMessagesLoaded + && messages.size() != 0) { + // In this case, we only have loaded merge commits. Load more messages + ConfigurationManager::instance().loadConversationMessages(linked.owner.id, + conversationId, + messages.rbegin()->value( + "id"), + 2); + return; + } + invalidateModel(); + Q_EMIT linked.modelChanged(); + Q_EMIT linked.newMessagesAvailable(linked.owner.id, conversationId); + auto conversationIdx = indexOf(conversationId); + Q_EMIT linked.dataChanged(conversationIdx); + Q_EMIT linked.conversationMessagesLoaded(requestId, conversationId); + + if (allLoaded) { + conversation.allMessagesLoaded = true; + Q_EMIT linked.conversationUpdated(conversationId); + } + } catch (const std::exception& e) { + qDebug() << "messages loaded for not existing conversation"; + } +} + +void +ConversationModelPimpl::slotMessageReceived(const QString& accountId, + const QString& conversationId, + const MapStringString& message) +{ + if (accountId != linked.owner.id) { + return; + } + try { + auto& conversation = getConversationForUid(conversationId).get(); + if (message["type"].isEmpty()) { + return; + } + if (message["type"] == "application/update-profile") { + // Refresh infos + MapStringString details = ConfigurationManager::instance() + .conversationInfos(linked.owner.id, conversationId); + conversation.infos = details; + Q_EMIT linked.conversationUpdated(conversationId); + Q_EMIT linked.dataChanged(indexOf(conversationId)); + return; + } + if (message["type"] == "initial") { + conversation.allMessagesLoaded = true; + Q_EMIT linked.conversationUpdated(conversationId); + if (message.find("invited") == message.end()) { + return; + } + } + auto msgId = message["id"]; + auto msg = interaction::Info(message, linked.owner.profileInfo.uri); + api::datatransfer::Info info; + QString fileId; + + if (msg.type == interaction::Type::DATA_TRANSFER) { + // save data transfer interaction to db and assosiate daemon id with interaction id, + // conversation id and db id + QString fileId = message["fileId"]; + QString path; + qlonglong bytesProgress, totalSize; + linked.owner.dataTransferModel->fileTransferInfo(accountId, + conversationId, + fileId, + path, + totalSize, + bytesProgress); + QFileInfo fi(path); + if (fi.isSymLink()) { + msg.body = fi.symLinkTarget(); + } else { + msg.body = path; + } + msg.status = bytesProgress == 0 ? interaction::Status::TRANSFER_AWAITING_HOST + : bytesProgress == totalSize ? interaction::Status::TRANSFER_FINISHED + : interaction::Status::TRANSFER_ONGOING; + linked.owner.dataTransferModel->registerTransferId(fileId, msgId); + } else if (msg.type == interaction::Type::CALL) { + msg.body = storage::getCallInteractionString(msg.authorUri, msg.duration); + } else if (msg.type == interaction::Type::CONTACT) { + auto bestName = msg.authorUri == linked.owner.profileInfo.uri + ? linked.owner.accountModel->bestNameForAccount(linked.owner.id) + : linked.owner.contactModel->bestNameForContact(msg.authorUri); + msg.body = interaction::getContactInteractionString(bestName, + interaction::to_action( + message["action"])); + } else if (msg.type == interaction::Type::TEXT + && msg.authorUri != linked.owner.profileInfo.uri) { + conversation.unreadMessages++; + } + if (!insertSwarmInteraction(msgId, msg, conversation, false)) { + // message already exists + return; + } + if (msg.type == interaction::Type::MERGE) { + invalidateModel(); + return; + } + conversation.lastMessageUid = msgId; + invalidateModel(); + if (!interaction::isOutgoing(msg)) { + Q_EMIT behaviorController.newUnreadInteraction(linked.owner.id, + conversationId, + msgId, + msg); + } + Q_EMIT linked.newInteraction(conversationId, msgId, msg); + Q_EMIT linked.modelChanged(); + if (msg.status == interaction::Status::TRANSFER_AWAITING_HOST) { + handleIncomingFile(conversationId, + msgId, + message["displayName"], + message["totalSize"].toInt()); + } + Q_EMIT linked.dataChanged(indexOf(conversationId)); + } catch (const std::exception& e) { + qDebug() << "messages received for not existing conversation"; + } +} + +bool +ConversationModelPimpl::insertSwarmInteraction(const QString& interactionId, + const interaction::Info& interaction, + conversation::Info& conversation, + bool insertAtBegin) +{ + std::lock_guard<std::mutex> lk(interactionsLocks[conversation.uid]); + int index = conversation.interactions->indexOfMessage(interaction.parentId); + if (index >= 0) { + auto result = conversation.interactions->insert(index + 1, + qMakePair(interactionId, interaction)); + if (!result.second) + return false; + } else { + auto result = conversation.interactions->insert(std::make_pair(interactionId, interaction), + insertAtBegin); + if (!result.second) + return false; + if (!interaction.parentId.isEmpty()) + conversation.parentsId[interactionId] = interaction.parentId; + } + if (!conversation.parentsId.values().contains(interactionId)) { + return true; + } + auto msgIds = conversation.parentsId.keys(interactionId); + conversation.interactions->moveMessages(msgIds, interactionId); + for (auto& msg : msgIds) + conversation.parentsId.remove(msg); + return true; +} + +void +ConversationModelPimpl::slotConversationRequestReceived(const QString& accountId, + const QString&, + const MapStringString& metadatas) +{ + if (accountId != linked.owner.id) { + return; + } + addConversationRequest(metadatas); +} + +void +ConversationModelPimpl::slotConversationRequestDeclined(const QString& accountId, + const QString& convId) +{ + auto conversationIndex = indexOf(convId); + if (accountId != linked.owner.id || conversationIndex < 0) + return; + eraseConversation(conversationIndex); + Q_EMIT linked.conversationRemoved(convId); + Q_EMIT linked.modelChanged(); +} + +void +ConversationModelPimpl::slotConversationReady(const QString& accountId, + const QString& conversationId) +{ + // we receive this signal after we accept or after we send a conversation request + if (accountId != linked.owner.id) { + return; + } + // remove non swarm conversation that was added from slotContactAdded + const VectorMapStringString& members = ConfigurationManager::instance() + .getConversationMembers(accountId, conversationId); + QVector<member::Member> participants; + // it means conversation with one participant. In this case we could have non swarm conversation + bool shouldRemoveNonSwarmConversation = members.size() == 2; + for (const auto& member : members) { + participants.append({member["uri"], api::member::to_role(member["role"])}); + if (shouldRemoveNonSwarmConversation) { + try { + auto& conversation = getConversationForPeerUri(member["uri"]).get(); + // remove non swarm conversation + if (conversation.isLegacy()) { + eraseConversation(conversation.uid); + storage::removeContactConversations(db, member["uri"]); + invalidateModel(); + Q_EMIT linked.conversationRemoved(conversation.uid); + Q_EMIT linked.modelChanged(); + } + } catch (...) { + } + } + } + + int conversationIdx = indexOf(conversationId); + bool conversationExists = conversationIdx >= 0; + + if (!conversationExists) + addSwarmConversation(conversationId); + auto& conversation = getConversationForUid(conversationId).get(); + if (conversationExists) { + // if swarm request already exists, update participnts + auto& conversation = getConversationForUid(conversationId).get(); + conversation.participants = participants; + const MapStringString& details = ConfigurationManager::instance() + .conversationInfos(accountId, conversationId); + conversation.infos = details; + conversation.mode = conversation::to_mode(details["mode"].toInt()); + conversation.isRequest = false; + conversation.needsSyncing = false; + Q_EMIT linked.conversationUpdated(conversationId); + Q_EMIT linked.dataChanged(conversationIdx); + ConfigurationManager::instance().loadConversationMessages(linked.owner.id, + conversationId, + "", + 0); + auto& peers = peersForConversation(conversation); + if (peers.size() == 1) + Q_EMIT linked.conversationReady(conversationId, peers.front()); + return; + } + invalidateModel(); + // we use conversationReady callback only for conversation with one participant. We could use + // participants.front() + auto& peers = peersForConversation(conversation); + if (peers.size() == 1) + Q_EMIT linked.conversationReady(conversationId, peers.front()); + Q_EMIT linked.newConversation(conversationId); + Q_EMIT linked.modelChanged(); +} + +void +ConversationModelPimpl::slotConversationRemoved(const QString& accountId, + const QString& conversationId) +{ + auto conversationIndex = indexOf(conversationId); + if (accountId != linked.owner.id || conversationIndex < 0) { + return; + } + try { + auto removeConversation = [&]() { + // remove swarm conversation + eraseConversation(conversationIndex); + invalidateModel(); + Q_EMIT linked.conversationRemoved(conversationId); + }; + + auto& conversation = getConversationForUid(conversationId).get(); + auto& peers = peersForConversation(conversation); + + // if swarm conversation removed but we still have contact we create non swarm conversation. + // we should create non swarm conversation only for removed one-to-one conversation. + if (conversation.mode == conversation::Mode::ONE_TO_ONE) { + if (peers.isEmpty()) { + removeConversation(); + return; + } + + auto contactId = peers.first(); + removeConversation(); + + auto conv = storage::getConversationsWithPeer(db, contactId); + if (conv.empty()) { + conv.push_back(storage::beginConversationWithPeer(db, contactId)); + } + addConversationWith(conv[0], contactId, false); + Q_EMIT linked.newConversation(conv[0]); + } else { + removeConversation(); + } + } catch (const std::exception& e) { + qWarning() << e.what(); + } +} + +void +ConversationModelPimpl::slotConversationMemberEvent(const QString& accountId, + const QString& conversationId, + const QString& memberUri, + int event) +{ + if (accountId != linked.owner.id || indexOf(conversationId) < 0) { + return; + } + if (event == 0 /* add */) { + // clear search result + for (unsigned int i = 0; i < searchResults.size(); ++i) { + if (searchResults.at(i).uid == memberUri) + searchResults.erase(searchResults.begin() + i); + } + } + // update participants + auto& conversation = getConversationForUid(conversationId).get(); + const VectorMapStringString& members + = ConfigurationManager::instance().getConversationMembers(linked.owner.id, conversationId); + QVector<member::Member> participants; + VectorString membersRemaining; + for (auto& member : members) { + participants.append(member::Member {member["uri"], member::to_role(member["role"])}); + if (member["role"] != "left") + membersRemaining.append(member["uri"]); + } + conversation.participants = participants; + conversation.readOnly = membersRemaining == VectorString(1, linked.owner.profileInfo.uri); + invalidateModel(); + Q_EMIT linked.modelChanged(); + Q_EMIT linked.conversationUpdated(conversationId); + Q_EMIT linked.dataChanged(indexOf(conversationId)); +} + +void +ConversationModelPimpl::slotIncomingContactRequest(const QString& contactUri) +{ + // It is contact request. But for compatibility with swarm conversations we add it like non + // swarm conversation request. + addContactRequest(contactUri); +} + +void +ConversationModelPimpl::slotContactAdded(const QString& contactUri) +{ + auto conv = storage::getConversationsWithPeer(db, contactUri); + bool addConversation = false; + bool removeConversation = false; + try { + auto& conversation = getConversationForPeerUri(contactUri).get(); + // swarm conversation we update when receive conversation ready signal. + if (conversation.isSwarm()) { + MapStringString details = ConfigurationManager::instance() + .conversationInfos(linked.owner.id, conversation.uid); + bool needsSyncing = details["syncing"] == "true"; + if (conversation.needsSyncing != needsSyncing) { + conversation.isRequest = false; + conversation.needsSyncing = needsSyncing; + Q_EMIT linked.dataChanged(indexOf(conversation.uid)); + Q_EMIT linked.conversationUpdated(conversation.uid); + invalidateModel(); + Q_EMIT linked.modelChanged(); + } + return; + } else { + conversation.isRequest = false; + } + if (conv.empty()) { + conv.push_back(storage::beginConversationWithPeer(db, contactUri)); + } + // remove temporary conversation that was added when receiving an incoming request + removeConversation = indexOf(contactUri) != -1 && indexOf(conv[0]) == -1; + + // add a conversation if not exists + addConversation = indexOf(conv[0]) == -1; + } catch (std::out_of_range&) { + /* + if the conversation does not exists we save it to DB and add non-swarm + conversation to the conversion list. After receiving a conversation request or + conversation ready signal swarm conversation should be updated and removed from DB. + */ + addConversation = true; + if (conv.empty()) { + conv.push_back(storage::beginConversationWithPeer(db, + contactUri, + true, + linked.owner.contactModel->getAddedTs( + contactUri))); + } + } + if (addConversation) { + addConversationWith(conv[0], contactUri, false); + Q_EMIT linked.conversationReady(conv[0], contactUri); + Q_EMIT linked.newConversation(conv[0]); + } + if (removeConversation) { + eraseConversation(indexOf(contactUri)); + invalidateModel(); + Q_EMIT linked.conversationRemoved(contactUri); + Q_EMIT linked.modelChanged(); + } else if (!addConversation) { + invalidateModel(); + Q_EMIT linked.modelChanged(); + Q_EMIT linked.conversationReady(conv[0], contactUri); + } +} + +void +ConversationModelPimpl::addContactRequest(const QString& contactUri) +{ + try { + getConversationForPeerUri(contactUri).get(); + // request from contact already exists, return + return; + } catch (std::out_of_range&) { + // no conversation exists. Add contact request + conversation::Info conversation; + conversation.uid = contactUri; + conversation.accountId = linked.owner.id; + conversation.participants = {{contactUri, member::Role::INVITED}}; + conversation.mode = conversation::Mode::NON_SWARM; + conversation.isRequest = true; + emplaceBackConversation(std::move(conversation)); + invalidateModel(); + Q_EMIT linked.newConversation(contactUri); + Q_EMIT linked.modelChanged(); + } +} + +void +ConversationModelPimpl::addConversationRequest(const MapStringString& convRequest) +{ + auto convId = convRequest["id"]; + auto convIdx = indexOf(convId); + if (convIdx != -1) + return; + + auto peerUri = convRequest["from"]; + auto mode = conversation::to_mode(convRequest["mode"].toInt()); + if (mode == conversation::Mode::ONE_TO_ONE) { + try { + // check if we have contact request for peer + auto& conv = getConversationForPeerUri(peerUri).get(); + if (conv.mode == conversation::Mode::NON_SWARM) { + // update conversation and remove the invite conversation from db + conv.mode = mode; + conv.uid = convId; + storage::removeContactConversations(db, peerUri); + invalidateModel(); + Q_EMIT linked.modelChanged(); + return; + } + } catch (std::out_of_range&) { + qWarning() << "Couldn't find contact request conversation for" << peerUri; + } + } + + // add the author to the contact model's contact list as a PENDING + // if they aren't already a contact + auto isSelf = linked.owner.profileInfo.uri == peerUri; + if (isSelf) + return; + linked.owner.contactModel->addToContacts(peerUri); + + const MapStringString& details = ConfigurationManager::instance() + .conversationInfos(linked.owner.id, convId); + conversation::Info conversation; + conversation.uid = convId; + conversation.infos = details; + conversation.accountId = linked.owner.id; + conversation.participants = {{linked.owner.profileInfo.uri, member::Role::INVITED}, + {peerUri, member::Role::MEMBER}}; + conversation.mode = mode; + conversation.isRequest = true; + emplaceBackConversation(std::move(conversation)); + invalidateModel(); + Q_EMIT linked.newConversation(convId); + Q_EMIT linked.modelChanged(); +} + +void +ConversationModelPimpl::slotPendingContactAccepted(const QString& uri) +{ + auto type = linked.owner.profileInfo.type; + try { + type = linked.owner.contactModel->getContact(uri).profileInfo.type; + } catch (std::out_of_range& e) { + } + profile::Info profileInfo {uri, {}, {}, type}; + storage::createOrUpdateProfile(linked.owner.id, profileInfo, true); + auto convs = storage::getConversationsWithPeer(db, uri); + if (!convs.empty()) { + try { + auto contact = linked.owner.contactModel->getContact(uri); + auto interaction = interaction::Info {uri, + {}, + std::time(nullptr), + 0, + interaction::Type::CONTACT, + interaction::Status::SUCCESS, + true}; + auto msgId = storage::addMessageToConversation(db, convs[0], interaction); + interaction.body = storage::getContactInteractionString(uri, + interaction::Status::SUCCESS); + auto convIdx = indexOf(convs[0]); + if (convIdx >= 0) { + std::lock_guard<std::mutex> lk(interactionsLocks[conversations[convIdx].uid]); + conversations[convIdx].interactions->emplace(msgId, interaction); + } + filteredConversations.invalidate(); + Q_EMIT linked.newInteraction(convs[0], msgId, interaction); + Q_EMIT linked.dataChanged(convIdx); + } catch (std::out_of_range& e) { + qDebug() << "ConversationModelPimpl::slotContactAdded can't find contact"; + } + } +} + +void +ConversationModelPimpl::slotContactRemoved(const QString& uri) +{ + std::vector<QString> convIdsToRemove; + + // save the ids to remove from the list + for (auto i : getIndicesForContact(uri)) { + convIdsToRemove.emplace_back(conversations[i].uid); + } + + // actually remove them from the list + for (auto id : convIdsToRemove) { + eraseConversation(id); + Q_EMIT linked.conversationRemoved(id); + } + + invalidateModel(); + Q_EMIT linked.modelChanged(); +} + +void +ConversationModelPimpl::slotContactModelUpdated(const QString& uri) +{ + // Update presence for all conversations with this peer + for (auto& conversation : conversations) { + auto members = peersForConversation(conversation); + if (members.indexOf(uri) != -1) { + invalidateModel(); + Q_EMIT linked.conversationUpdated(conversation.uid); + Q_EMIT linked.dataChanged(indexOf(conversation.uid)); + } + } + + if (currentFilter.isEmpty()) { + if (searchResults.empty()) + return; + searchResults.clear(); + Q_EMIT linked.searchResultUpdated(); + return; + } + searchResults.clear(); + auto users = linked.owner.contactModel->getSearchResults(); + for (auto& user : users) { + conversation::Info conversationInfo; + conversationInfo.uid = user.profileInfo.uri; + conversationInfo.participants.append( + member::Member {user.profileInfo.uri, member::Role::MEMBER}); + conversationInfo.accountId = linked.owner.id; + searchResults.emplace_front(std::move(conversationInfo)); + } + Q_EMIT linked.searchResultUpdated(); +} + +void +ConversationModelPimpl::addSwarmConversation(const QString& convId) +{ + QVector<member::Member> participants; + const VectorMapStringString& members = ConfigurationManager::instance() + .getConversationMembers(linked.owner.id, convId); + auto accountURI = linked.owner.profileInfo.uri; + QString otherMember; + const MapStringString& details = ConfigurationManager::instance() + .conversationInfos(linked.owner.id, convId); + auto mode = conversation::to_mode(details["mode"].toInt()); + conversation::Info conversation; + conversation.infos = details; + conversation.uid = convId; + conversation.accountId = linked.owner.id; + QString lastRead; + VectorString membersLeft; + for (auto& member : members) { + // this check should be removed once all usage of participants replaced by + // peersForConversation. We should have ourself in participants list + // Note: if members.size() == 1, it's a conv with self so we're also the peer + participants.append(member::Member {member["uri"], member::to_role(member["role"])}); + if (mode == conversation::Mode::ONE_TO_ONE && member["uri"] != accountURI) { + otherMember = member["uri"]; + } else if (member["uri"] == accountURI) { + lastRead = member["lastDisplayed"]; + } + if (member["uri"] != accountURI) + conversation.interactions->setRead(member["uri"], member["lastDisplayed"]); + if (member["role"] == "left") + membersLeft.append(member["uri"]); + } + conversation.readOnly = mode == conversation::Mode::ONE_TO_ONE && membersLeft.size() == 1; + conversation.participants = participants; + conversation.mode = mode; + conversation.unreadMessages = ConfigurationManager::instance().countInteractions(linked.owner.id, + convId, + lastRead, + "", + accountURI); + if (mode == conversation::Mode::ONE_TO_ONE && !otherMember.isEmpty()) { + try { + conversation.confId = linked.owner.callModel->getConferenceFromURI(otherMember).id; + } catch (...) { + conversation.confId = ""; + } + try { + conversation.callId = linked.owner.callModel->getCallFromURI(otherMember).id; + } catch (...) { + conversation.callId = ""; + } + } + // If conversation has only one peer it is possible that non swarm conversation was created. + // remove non swarm conversation + auto& peers = peersForConversation(conversation); + if (peers.size() == 1) { + try { + auto& participantId = peers.front(); + auto& conv = getConversationForPeerUri(participantId).get(); + if (conv.mode == conversation::Mode::NON_SWARM) { + eraseConversation(conv.uid); + invalidateModel(); + Q_EMIT linked.conversationRemoved(conv.uid); + storage::removeContactConversations(db, participantId); + } + } catch (...) { + } + } + if (details["syncing"] == "true") { + conversation.needsSyncing = true; + Q_EMIT linked.conversationUpdated(conversation.uid); + Q_EMIT linked.dataChanged(indexOf(conversation.uid)); + } + emplaceBackConversation(std::move(conversation)); + ConfigurationManager::instance().loadConversationMessages(linked.owner.id, convId, "", 1); +} + +void +ConversationModelPimpl::addConversationWith(const QString& convId, + const QString& contactUri, + bool isRequest) +{ + conversation::Info conversation; + conversation.uid = convId; + conversation.accountId = linked.owner.id; + conversation.participants = {{contactUri, member::Role::MEMBER}}; + conversation.mode = conversation::Mode::NON_SWARM; + conversation.needsSyncing = false; + conversation.isRequest = isRequest; + + try { + conversation.confId = linked.owner.callModel->getConferenceFromURI(contactUri).id; + } catch (...) { + conversation.confId = ""; + } + try { + conversation.callId = linked.owner.callModel->getCallFromURI(contactUri).id; + } catch (...) { + conversation.callId = ""; + } + storage::getHistory(db, conversation); + std::vector<std::function<void(void)>> updateSlots; + { + std::lock_guard<std::mutex> lk(interactionsLocks[convId]); + for (auto& interaction : (*(conversation.interactions))) { + if (interaction.second.status != interaction::Status::SENDING) { + continue; + } + // Get the message status from daemon, else unknown + auto id = storage::getDaemonIdByInteractionId(db, interaction.first); + int status = 0; + if (id.isEmpty()) { + continue; + } + try { + auto msgId = std::stoull(id.toStdString()); + status = ConfigurationManager::instance().getMessageStatus(msgId); + updateSlots.emplace_back([this, convId, contactUri, id, status]() -> void { + auto accId = linked.owner.id; + slotUpdateInteractionStatus(accId, convId, contactUri, id, status); + }); + } catch (const std::exception& e) { + qDebug() << "message id was invalid"; + } + } + } + for (const auto& s : updateSlots) { + s(); + } + + conversation.unreadMessages = getNumberOfUnreadMessagesFor(convId); + + emplaceBackConversation(std::move(conversation)); + invalidateModel(); +} + +int +ConversationModelPimpl::indexOf(const QString& uid) const +{ + for (unsigned int i = 0; i < conversations.size(); ++i) { + if (conversations.at(i).uid == uid) + return i; + } + return -1; +} + +std::reference_wrapper<conversation::Info> +ConversationModelPimpl::getConversation(const FilterPredicate& pred, + const bool searchResultIncluded) const +{ + auto conv = std::find_if(conversations.cbegin(), conversations.cend(), pred); + if (conv != conversations.cend()) { + return std::remove_const_t<conversation::Info&>(*conv); + } + + if (searchResultIncluded) { + auto sr = std::find_if(searchResults.cbegin(), searchResults.cend(), pred); + if (sr != searchResults.cend()) { + return std::remove_const_t<conversation::Info&>(*sr); + } + } + + throw std::out_of_range("Conversation out of range"); +} + +std::reference_wrapper<conversation::Info> +ConversationModelPimpl::getConversationForUid(const QString& uid, + const bool searchResultIncluded) const +{ + return getConversation([uid](const conversation::Info& conv) -> bool { return uid == conv.uid; }, + searchResultIncluded); +} + +std::reference_wrapper<conversation::Info> +ConversationModelPimpl::getConversationForPeerUri(const QString& uri, + const bool searchResultIncluded) const +{ + return getConversation( + [this, uri](const conversation::Info& conv) -> bool { + if (!conv.isCoreDialog()) { + return false; + } + auto members = peersForConversation(conv); + if (members.isEmpty()) + return false; + return members.indexOf(uri) != -1; + }, + searchResultIncluded); +} + +std::vector<int> +ConversationModelPimpl::getIndicesForContact(const QString& uri, bool writable) const +{ + std::vector<int> ret; + for (unsigned int i = 0; i < conversations.size(); ++i) { + const auto& convInfo = conversations.at(i); + if (!convInfo.isCoreDialog() || (writable && convInfo.readOnly)) { + continue; + } + auto peers = peersForConversation(convInfo); + if (!peers.isEmpty() && peers.front() == uri) { + ret.emplace_back(i); + } + } + return ret; +} + +void +ConversationModelPimpl::slotIncomingCall(const QString& fromId, const QString& callId) +{ + auto convIds = storage::getConversationsWithPeer(db, fromId); + if (convIds.empty()) { + // in case if we receive call after removing contact add conversation request; + try { + auto contact = linked.owner.contactModel->getContact(fromId); + if (contact.profileInfo.type == profile::Type::PENDING && !contact.isBanned + && fromId != linked.owner.profileInfo.uri) { + addContactRequest(fromId); + } + } catch (const std::out_of_range&) { + } + } + + auto conversationIndices = getIndicesForContact(fromId); + if (conversationIndices.empty()) { + qDebug() << "ConversationModelPimpl::slotIncomingCall, but conversation not found"; + return; // Not a contact + } + + auto& conversation = conversations.at(conversationIndices.at(0)); + qDebug() << "Add call to conversation with " << fromId; + conversation.callId = callId; + + addOrUpdateCallMessage(callId, fromId, true); + Q_EMIT behaviorController.showIncomingCallView(linked.owner.id, conversation.uid); +} + +void +ConversationModelPimpl::slotCallStatusChanged(const QString& callId, int code) +{ + Q_UNUSED(code) + // Get conversation + auto i = std::find_if(conversations.begin(), + conversations.end(), + [callId](const conversation::Info& conversation) { + return conversation.callId == callId; + }); + + try { + auto call = linked.owner.callModel->getCall(callId); + if (i == conversations.end()) { + // In this case, the user didn't pass through placeCall + // This means that a participant was invited to a call + // or a call was placed via dbus. + // We have to update the model + for (auto& conversation : conversations) { + auto& peers = peersForConversation(conversation); + if (peers.size() != 1) { + continue; + } + if (peers.front() == call.peerUri) { + conversation.callId = callId; + // Update interaction status + invalidateModel(); + Q_EMIT linked.selectConversation(conversation.uid); + Q_EMIT linked.conversationUpdated(conversation.uid); + Q_EMIT linked.dataChanged(indexOf(conversation.uid)); + } + } + } else if (i != conversations.end()) { + // Update interaction status + invalidateModel(); + Q_EMIT linked.selectConversation(i->uid); + Q_EMIT linked.conversationUpdated(i->uid); + Q_EMIT linked.dataChanged(indexOf(i->uid)); + } + } catch (std::out_of_range& e) { + qDebug() << "ConversationModelPimpl::slotCallStatusChanged can't get inexistant call"; + } +} + +void +ConversationModelPimpl::slotCallStarted(const QString& callId) +{ + try { + auto call = linked.owner.callModel->getCall(callId); + addOrUpdateCallMessage(callId, call.peerUri.remove("ring:"), !call.isOutgoing); + } catch (std::out_of_range& e) { + qDebug() << "ConversationModelPimpl::slotCallStarted can't start inexistant call"; + } +} + +void +ConversationModelPimpl::slotCallEnded(const QString& callId) +{ + try { + auto call = linked.owner.callModel->getCall(callId); + // get duration + std::time_t duration = 0; + if (call.startTime.time_since_epoch().count() != 0) { + auto duration_ns = std::chrono::steady_clock::now() - call.startTime; + duration = std::chrono::duration_cast<std::chrono::seconds>(duration_ns).count(); + } + // add or update call interaction with duration + addOrUpdateCallMessage(callId, call.peerUri.remove("ring:"), !call.isOutgoing, duration); + /* Reset the callId stored in the conversation. + Do not call selectConversation() since it is already done in slotCallStatusChanged. */ + for (auto& conversation : conversations) + if (conversation.callId == callId) { + conversation.callId = ""; + conversation.confId = ""; // The participant is detached + invalidateModel(); + Q_EMIT linked.conversationUpdated(conversation.uid); + Q_EMIT linked.dataChanged(indexOf(conversation.uid)); + } + } catch (std::out_of_range& e) { + qDebug() << "ConversationModelPimpl::slotCallEnded can't end inexistant call"; + } +} + +void +ConversationModelPimpl::addOrUpdateCallMessage(const QString& callId, + const QString& from, + bool incoming, + const std::time_t& duration) +{ + // do not save call interaction for swarm conversation + auto convIds = storage::getConversationsWithPeer(db, from); + if (convIds.empty()) { + // in case if we receive call after removing contact add conversation request; + try { + auto contact = linked.owner.contactModel->getContact(from); + if (contact.profileInfo.type == profile::Type::PENDING && !contact.isBanned) { + addContactRequest(from); + convIds.push_back(storage::beginConversationWithPeer(db, contact.profileInfo.uri)); + auto& conv = getConversationForPeerUri(contact.profileInfo.uri).get(); + conv.uid = convIds[0]; + } else { + return; + } + } catch (const std::out_of_range&) { + return; + } + } + // Get conversation + auto conv_it = std::find_if(conversations.begin(), + conversations.end(), + [&callId](const conversation::Info& conversation) { + return conversation.callId == callId; + }); + if (conv_it == conversations.end()) { + return; + } + auto uid = conv_it->uid; + auto uriString = incoming ? storage::prepareUri(from, linked.owner.profileInfo.type) : ""; + auto msg = interaction::Info {uriString, + {}, + std::time(nullptr), + duration, + interaction::Type::CALL, + interaction::Status::SUCCESS, + true}; + // update the db + auto msgId = storage::addOrUpdateMessage(db, conv_it->uid, msg, callId); + // now set the formatted call message string in memory only + msg.body = storage::getCallInteractionString(uriString, duration); + bool newInteraction = false; + { + std::lock_guard<std::mutex> lk(interactionsLocks[conv_it->uid]); + auto interactionIt = conv_it->interactions->find(msgId); + newInteraction = interactionIt == conv_it->interactions->end(); + if (newInteraction) { + conv_it->lastMessageUid = msgId; + conv_it->interactions->emplace(msgId, msg); + } else { + interactionIt->second = msg; + conv_it->interactions->emitDataChanged(interactionIt); + } + } + + if (newInteraction) + Q_EMIT linked.newInteraction(conv_it->uid, msgId, msg); + else + Q_EMIT linked.interactionStatusUpdated(conv_it->uid, msgId, msg); + + invalidateModel(); + Q_EMIT linked.modelChanged(); + Q_EMIT linked.dataChanged(static_cast<int>(std::distance(conversations.begin(), conv_it))); +} + +void +ConversationModelPimpl::slotNewAccountMessage(const QString& accountId, + const QString& peerId, + const QString& msgId, + const MapStringString& payloads) +{ + if (accountId != linked.owner.id) + return; + + for (const auto& payload : payloads.keys()) { + if (payload.contains("text/plain")) { + addIncomingMessage(peerId, payloads.value(payload), 0, msgId); + } + } +} + +void +ConversationModelPimpl::slotIncomingCallMessage(const QString& accountId, + const QString& callId, + const QString& from, + const QString& body) +{ + if (accountId != linked.owner.id || !linked.owner.callModel->hasCall(callId)) + return; + + auto& call = linked.owner.callModel->getCall(callId); + if (call.type == call::Type::CONFERENCE) { + // Show messages in all conversations for conferences. + for (const auto& conversation : conversations) { + if (conversation.confId == callId) { + if (conversation.participants.empty()) { + continue; + } + addIncomingMessage(from, body); + } + } + } else { + addIncomingMessage(from, body); + } +} + +QString +ConversationModelPimpl::addIncomingMessage(const QString& peerId, + const QString& body, + const uint64_t& timestamp, + const QString& daemonId) +{ + auto convIds = storage::getConversationsWithPeer(db, peerId); + bool isRequest = false; + if (convIds.empty()) { + // in case if we receive a message after removing contact, add a conversation request + try { + auto contact = linked.owner.contactModel->getContact(peerId); + isRequest = contact.profileInfo.type == profile::Type::PENDING; + if (isRequest && !contact.isBanned && peerId != linked.owner.profileInfo.uri) { + addContactRequest(peerId); + convIds.push_back(storage::beginConversationWithPeer(db, contact.profileInfo.uri)); + auto& conv = getConversationForPeerUri(contact.profileInfo.uri).get(); + conv.uid = convIds[0]; + } else { + return ""; + } + } catch (const std::out_of_range&) { + return ""; + } + } + auto msg = interaction::Info {peerId, + body, + timestamp == 0 ? std::time(nullptr) + : static_cast<time_t>(timestamp), + 0, + interaction::Type::TEXT, + interaction::Status::SUCCESS, + false}; + auto msgId = storage::addMessageToConversation(db, convIds[0], msg); + if (!daemonId.isEmpty()) { + storage::addDaemonMsgId(db, msgId, daemonId); + } + auto conversationIdx = indexOf(convIds[0]); + // Add the conversation if not already here + if (conversationIdx == -1) { + addConversationWith(convIds[0], peerId, isRequest); + Q_EMIT linked.newConversation(convIds[0]); + } else { + { + std::lock_guard<std::mutex> lk(interactionsLocks[conversations[conversationIdx].uid]); + conversations[conversationIdx].interactions->emplace(msgId, msg); + } + conversations[conversationIdx].lastMessageUid = msgId; + conversations[conversationIdx].unreadMessages = getNumberOfUnreadMessagesFor(convIds[0]); + } + + Q_EMIT behaviorController.newUnreadInteraction(linked.owner.id, convIds[0], msgId, msg); + Q_EMIT linked.newInteraction(convIds[0], msgId, msg); + + invalidateModel(); + Q_EMIT linked.modelChanged(); + Q_EMIT linked.dataChanged(conversationIdx); + + return msgId; +} + +void +ConversationModelPimpl::slotCallAddedToConference(const QString& callId, const QString& confId) +{ + for (auto& conversation : conversations) { + if (conversation.callId == callId && conversation.confId != confId) { + conversation.confId = confId; + invalidateModel(); + // Refresh the conference status only if attached + MapStringString confDetails = CallManager::instance() + .getConferenceDetails(linked.owner.id, confId); + if (confDetails["STATE"] == "ACTIVE_ATTACHED") + Q_EMIT linked.selectConversation(conversation.uid); + } + } +} + +void +ConversationModelPimpl::slotUpdateInteractionStatus(const QString& accountId, + const QString& conversationId, + const QString& peerId, + const QString& messageId, + int status) +{ + if (accountId != linked.owner.id) { + return; + } + // it may be not swarm conversation check in db + if (conversationId.isEmpty() || conversationId == linked.owner.profileInfo.uri) { + auto convIds = storage::getConversationsWithPeer(db, peerId); + if (convIds.empty()) { + return; + } + auto conversationIdx = indexOf(convIds[0]); + auto& conversation = conversations[conversationIdx]; + auto newStatus = interaction::Status::INVALID; + switch (static_cast<DRing::Account::MessageStates>(status)) { + case DRing::Account::MessageStates::SENDING: + newStatus = interaction::Status::SENDING; + break; + case DRing::Account::MessageStates::CANCELLED: + newStatus = interaction::Status::TRANSFER_CANCELED; + break; + case DRing::Account::MessageStates::SENT: + newStatus = interaction::Status::SUCCESS; + break; + case DRing::Account::MessageStates::FAILURE: + newStatus = interaction::Status::FAILURE; + break; + case DRing::Account::MessageStates::DISPLAYED: + newStatus = interaction::Status::DISPLAYED; + break; + case DRing::Account::MessageStates::UNKNOWN: + default: + newStatus = interaction::Status::UNKNOWN; + break; + } + auto idString = messageId; + // for not swarm conversation messageId in hexdesimal string format. Convert to normal string + // TODO messageId should be received from daemon in string format + if (static_cast<DRing::Account::MessageStates>(status) + == DRing::Account::MessageStates::DISPLAYED) { + std::istringstream ss(messageId.toStdString()); + ss >> std::hex; + uint64_t id; + if (!(ss >> id)) + return; + idString = QString::number(id); + } + // Update database + auto interactionId = storage::getInteractionIdByDaemonId(db, idString); + if (interactionId.isEmpty()) { + return; + } + auto msgId = interactionId; + storage::updateInteractionStatus(db, msgId, newStatus); + // Update conversations + interaction::Info itCopy; + bool emitUpdated = false; + bool updateDisplayedUid = false; + QString oldDisplayedUid = 0; + { + std::lock_guard<std::mutex> lk(interactionsLocks[conversation.uid]); + auto& interactions = conversation.interactions; + auto it = interactions->find(msgId); + auto messageId = conversation.interactions->getRead(peerId); + if (it != interactions->end()) { + it->second.status = newStatus; + interactions->emitDataChanged(it, {MessageList::Role::Status}); + bool interactionDisplayed = newStatus == interaction::Status::DISPLAYED + && isOutgoing(it->second); + if (messageId != "") { + auto lastDisplayedIt = interactions->find(messageId); + bool interactionIsLast = lastDisplayedIt == interactions->end() + || lastDisplayedIt->second.timestamp + < it->second.timestamp; + updateDisplayedUid = interactionDisplayed && interactionIsLast; + if (updateDisplayedUid) { + oldDisplayedUid = messageId; + if (peerId != linked.owner.profileInfo.uri) + conversation.interactions->setRead(peerId, it->first); + } + } else { + oldDisplayedUid = ""; + if (peerId != linked.owner.profileInfo.uri) + conversation.interactions->setRead(peerId, it->first); + updateDisplayedUid = true; + } + emitUpdated = true; + itCopy = it->second; + } + } + if (updateDisplayedUid) { + Q_EMIT linked.displayedInteractionChanged(conversation.uid, + peerId, + oldDisplayedUid, + msgId); + } + if (emitUpdated) { + invalidateModel(); + Q_EMIT linked.interactionStatusUpdated(conversation.uid, msgId, itCopy); + } + return; + } + try { + auto& conversation = getConversationForUid(conversationId).get(); + if (conversation.mode != conversation::Mode::NON_SWARM) { + if (static_cast<DRing::Account::MessageStates>(status) + == DRing::Account::MessageStates::DISPLAYED) { + auto previous = conversation.interactions->getRead(peerId); + if (peerId != linked.owner.profileInfo.uri) + conversation.interactions->setRead(peerId, messageId); + else { + // Here, this means that the daemon synched the displayed message + // so, compute the number of unread messages. + conversation.unreadMessages = ConfigurationManager::instance() + .countInteractions(linked.owner.id, + conversationId, + messageId, + "", + peerId); + Q_EMIT linked.dataChanged(indexOf(conversationId)); + } + Q_EMIT linked.displayedInteractionChanged(conversationId, peerId, previous, messageId); + } + } + } catch (const std::out_of_range& e) { + qDebug() << "could not update message status for not existing conversation"; + } +} + +void +ConversationModelPimpl::slotConferenceRemoved(const QString& accountId, const QString& confId) +{ + if (accountId != linked.owner.id) + return; + // Get conversation + for (auto& i : conversations) { + if (i.confId == confId) { + i.confId = ""; + } + } +} + +void +ConversationModelPimpl::slotComposingStatusChanged(const QString& accountId, + const QString& convId, + const QString& contactUri, + bool isComposing) +{ + if (accountId != linked.owner.id) + return; + + try { + auto& conversation = getConversationForUid(convId).get(); + if (isComposing) + conversation.typers.insert(contactUri); + else + conversation.typers.remove(contactUri); + } catch (const std::out_of_range& e) { + qDebug() << "could not update message status for not existing conversation"; + } + + Q_EMIT linked.composingStatusChanged(convId, contactUri, isComposing); +} + +int +ConversationModelPimpl::getNumberOfUnreadMessagesFor(const QString& uid) +{ + return storage::countUnreadFromInteractions(db, uid); +} + +void +ConversationModel::setIsComposing(const QString& convUid, bool isComposing) +{ + try { + auto& conversation = pimpl_->getConversationForUid(convUid).get(); + QString to = conversation.mode != conversation::Mode::NON_SWARM + ? "swarm:" + convUid + : "jami:" + pimpl_->peersForConversation(conversation).front(); + ConfigurationManager::instance().setIsComposing(owner.id, to, isComposing); + } catch (...) { + } +} + +void +ConversationModel::sendFile(const QString& convUid, const QString& path, const QString& filename) +{ + try { + auto& conversation = pimpl_->getConversationForUid(convUid, true).get(); + if (conversation.isSwarm()) { + owner.dataTransferModel->sendFile(owner.id, "", convUid, path, filename); + return; + } + auto peers = pimpl_->peersForConversation(conversation); + if (peers.size() < 1) { + qDebug() << "send file error: could not send file in conversation with no participants"; + return; + } + /* isTemporary, and conversationReady callback used only for non-swarm conversation, + because for swarm, conversation already configured at this point. + Conversations for new contact from search result are NON_SWARM but after receiving + conversationReady callback could be updated to ONE_TO_ONE. We still use conversationReady + callback for one_to_one conversation to check if contact is blocked*/ + const auto peerId = peers.front(); + bool isTemporary = peerId == convUid; + + /* It is necessary to make a copy of convUid since it may very well point to + a field in the temporary conversation, which is going to be destroyed by + slotContactAdded() (indirectly triggered by sendContactrequest(). Not doing + so may result in use after free/crash. */ + auto convUidCopy = convUid; + + pimpl_->sendContactRequest(peerId); + + auto cb = ([this, peerId, path, filename](QString conversationId) { + try { + auto conversationOpt = getConversationForUid(conversationId); + if (!conversationOpt.has_value()) { + qDebug() << "Can't send file"; + return; + } + auto contactInfo = owner.contactModel->getContact(peerId); + if (contactInfo.isBanned) { + qDebug() << "ContactModel::sendFile: denied, contact is banned"; + return; + } + auto& conversation = conversationOpt->get(); + // for non swarm conversation id should be empty, so peerId will be takin in consideration + auto id = conversation.mode != conversation::Mode::NON_SWARM ? conversationId : ""; + owner.dataTransferModel->sendFile(owner.id, peerId, id, path, filename); + } catch (...) { + } + }); + + if (isTemporary) { + QMetaObject::Connection* const connection = new QMetaObject::Connection; + *connection = connect(this, + &ConversationModel::conversationReady, + [cb, connection, convUidCopy](QString conversationId, + QString participantId) { + if (participantId != convUidCopy) { + return; + } + cb(conversationId); + QObject::disconnect(*connection); + if (connection) { + delete connection; + } + }); + } else { + cb(convUidCopy); + } + } catch (const std::out_of_range& e) { + qDebug() << "could not send file to not existing conversation"; + } +} + +void +ConversationModel::acceptTransfer(const QString& convUid, const QString& interactionId) +{ + lrc::api::datatransfer::Info info = {}; + getTransferInfo(convUid, interactionId, info); + acceptTransfer(convUid, interactionId, info.displayName); +} + +void +ConversationModel::acceptTransfer(const QString& convUid, + const QString& interactionId, + const QString& path) +{ + pimpl_->acceptTransfer(convUid, interactionId, path); +} + +void +ConversationModel::cancelTransfer(const QString& convUid, const QString& fileId) +{ + // For this action, we change interaction status before effective canceling as daemon will + // emit Finished event code immediately (before leaving this method) in non-DBus mode. + auto conversationIdx = pimpl_->indexOf(convUid); + interaction::Info itCopy; + bool emitUpdated = false; + if (conversationIdx != -1) { + std::lock_guard<std::mutex> lk(pimpl_->interactionsLocks[convUid]); + auto& interactions = pimpl_->conversations[conversationIdx].interactions; + auto it = interactions->find(fileId); + if (it != interactions->end()) { + it->second.status = interaction::Status::TRANSFER_CANCELED; + interactions->emitDataChanged(it, {MessageList::Role::Status}); + + // update information in the db + storage::updateInteractionStatus(pimpl_->db, + fileId, + interaction::Status::TRANSFER_CANCELED); + emitUpdated = true; + itCopy = it->second; + } + } + if (emitUpdated) { + // for swarm conversations we need to provide conversation id to accept file, for not swarm + // conversations we need peer uri + lrc::api::datatransfer::Info info = {}; + getTransferInfo(convUid, fileId, info); + // Forward cancel action to daemon (will invoke slotTransferStatusCanceled) + owner.dataTransferModel->cancel(owner.id, convUid, fileId); + pimpl_->invalidateModel(); + Q_EMIT interactionStatusUpdated(convUid, fileId, itCopy); + Q_EMIT pimpl_->behaviorController.newReadInteraction(owner.id, convUid, fileId); + } +} + +void +ConversationModel::getTransferInfo(const QString& conversationId, + const QString& interactionId, + datatransfer::Info& info) const +{ + auto convOpt = getConversationForUid(conversationId); + if (!convOpt) + return; + auto fileId = owner.dataTransferModel->getFileIdFromInteractionId(interactionId); + if (convOpt->get().mode == conversation::Mode::NON_SWARM) { + try { + owner.dataTransferModel->transferInfo(owner.id, fileId, info); + } catch (...) { + info.status = datatransfer::Status::INVALID; + } + } else { + QString path; + qlonglong bytesProgress, totalSize; + owner.dataTransferModel + ->fileTransferInfo(owner.id, conversationId, fileId, path, totalSize, bytesProgress); + info.path = path; + info.totalSize = totalSize; + info.progress = bytesProgress; + } +} + +int +ConversationModel::getNumberOfUnreadMessagesFor(const QString& convUid) +{ + return pimpl_->getNumberOfUnreadMessagesFor(convUid); +} + +bool +ConversationModelPimpl::usefulDataFromDataTransfer(const QString& fileId, + const datatransfer::Info& info, + QString& interactionId, + QString& conversationId) +{ + if (info.accountId != linked.owner.id) + return false; + try { + interactionId = linked.owner.dataTransferModel->getInteractionIdFromFileId(fileId); + conversationId = info.conversationId.isEmpty() + ? storage::conversationIdFromInteractionId(db, interactionId) + : info.conversationId; + } catch (const std::out_of_range& e) { + qWarning() << "Couldn't get interaction from daemon Id: " << fileId; + return false; + } + return true; +} + +void +ConversationModelPimpl::slotTransferStatusCreated(const QString& fileId, datatransfer::Info info) +{ + // check if transfer is for the current account + if (info.accountId != linked.owner.id) + return; + + const MapStringString accountDetails = ConfigurationManager::instance().getAccountDetails( + linked.owner.id); + if (accountDetails.empty()) + return; + // create a new conversation if needed + auto convIds = storage::getConversationsWithPeer(db, info.peerUri); + bool isRequest = false; + if (convIds.empty()) { + // in case if we receive file after removing contact add conversation request. If we have + // swarm request this function will do nothing. + try { + auto contact = linked.owner.contactModel->getContact(info.peerUri); + isRequest = contact.profileInfo.type == profile::Type::PENDING; + if (isRequest && !contact.isBanned && info.peerUri != linked.owner.profileInfo.uri) { + addContactRequest(info.peerUri); + convIds.push_back(storage::beginConversationWithPeer(db, contact.profileInfo.uri)); + auto& conv = getConversationForPeerUri(contact.profileInfo.uri).get(); + conv.uid = convIds[0]; + } else { + return; + } + } catch (const std::out_of_range&) { + return; + } + } + + // add interaction to the db + const auto& convId = convIds[0]; + auto interactionId = storage::addDataTransferToConversation(db, convId, info); + + // map fileId and interactionId for latter retrivial from client (that only known the interactionId) + linked.owner.dataTransferModel->registerTransferId(fileId, interactionId); + + auto interaction = interaction::Info {info.isOutgoing ? "" : info.peerUri, + info.isOutgoing ? info.path : info.displayName, + std::time(nullptr), + 0, + interaction::Type::DATA_TRANSFER, + interaction::Status::TRANSFER_CREATED, + false}; + + // prepare interaction Info and emit signal for the client + auto conversationIdx = indexOf(convId); + if (conversationIdx == -1) { + addConversationWith(convId, info.peerUri, isRequest); + Q_EMIT linked.newConversation(convId); + } else { + { + std::lock_guard<std::mutex> lk(interactionsLocks[conversations[conversationIdx].uid]); + conversations[conversationIdx].interactions->emplace(interactionId, interaction); + } + conversations[conversationIdx].lastMessageUid = interactionId; + conversations[conversationIdx].unreadMessages = getNumberOfUnreadMessagesFor(convId); + } + Q_EMIT behaviorController.newUnreadInteraction(linked.owner.id, + convId, + interactionId, + interaction); + Q_EMIT linked.newInteraction(convId, interactionId, interaction); + + invalidateModel(); + Q_EMIT linked.modelChanged(); + Q_EMIT linked.dataChanged(conversationIdx); +} + +void +ConversationModelPimpl::slotTransferStatusAwaitingPeer(const QString& fileId, + datatransfer::Info info) +{ + if (info.accountId != linked.owner.id) + return; + bool intUpdated; + updateTransferStatus(fileId, info, interaction::Status::TRANSFER_AWAITING_PEER, intUpdated); +} + +void +ConversationModelPimpl::slotTransferStatusAwaitingHost(const QString& fileId, + datatransfer::Info info) +{ + if (info.accountId != linked.owner.id) + return; + awaitingHost(fileId, info); +} + +bool +ConversationModelPimpl::hasOneOneSwarmWith(const QString& participant) +{ + try { + auto& conversation = getConversationForPeerUri(participant).get(); + return conversation.mode == conversation::Mode::ONE_TO_ONE; + } catch (std::out_of_range&) { + return false; + } +} + +void +ConversationModelPimpl::awaitingHost(const QString& fileId, datatransfer::Info info) +{ + if (info.accountId != linked.owner.id) + return; + QString interactionId; + QString conversationId; + if (not usefulDataFromDataTransfer(fileId, info, interactionId, conversationId)) + return; + + bool intUpdated; + + if (!updateTransferStatus(fileId, + info, + interaction::Status::TRANSFER_AWAITING_HOST, + intUpdated)) { + return; + } + if (!intUpdated) { + return; + } + auto conversationIdx = indexOf(conversationId); + auto& peers = peersForConversation(conversations[conversationIdx]); + // Only accept if contact is added or it is a group conversation + if (linked.owner.accountModel->autoTransferFromUntrusted && peers.size() == 1) { + try { + auto contactUri = peers.front(); + auto contactInfo = linked.owner.contactModel->getContact(contactUri); + if (contactInfo.profileInfo.type == profile::Type::PENDING) + return; + } catch (...) { + return; + } + } + handleIncomingFile(conversationId, interactionId, info.displayName, info.totalSize); +} + +void +ConversationModelPimpl::handleIncomingFile(const QString& convId, + const QString& interactionId, + const QString& displayName, + int totalSize) +{ + // If it's an accepted file type and less than 20 MB, accept transfer. + if (linked.owner.accountModel->autoTransferFromTrusted) { + if (linked.owner.accountModel->autoTransferSizeThreshold == 0 + || (totalSize > 0 + && static_cast<unsigned>(totalSize) + < linked.owner.accountModel->autoTransferSizeThreshold * 1024 * 1024)) { + acceptTransfer(convId, interactionId, displayName); + } + } +} + +void +ConversationModelPimpl::acceptTransfer(const QString& convUid, + const QString& interactionId, + const QString& path) +{ + auto& conversation = getConversationForUid(convUid).get(); + if (conversation.isLegacy()) { + // This is a fallback, will be removed when swarm will be mandatory + auto destinationDir = linked.owner.accountModel->downloadDirectory; + if (destinationDir.isEmpty()) { + return; + } +#ifdef Q_OS_WIN + if (destinationDir.right(1) != '/') { + destinationDir += "/"; + } +#endif + QDir dir = QFileInfo(destinationDir + path).absoluteDir(); + if (!dir.exists()) + dir.mkpath("."); + + auto acceptedFilePath = linked.owner.dataTransferModel->accept(linked.owner.id, + interactionId, + destinationDir + path); + auto fileId = linked.owner.dataTransferModel->getFileIdFromInteractionId(interactionId); + if (transfIdToDbIntId.find(fileId) != transfIdToDbIntId.end()) { + auto dbInteractionId = transfIdToDbIntId[fileId]; + storage::updateInteractionBody(db, dbInteractionId, acceptedFilePath); + storage::updateInteractionStatus(db, + dbInteractionId, + interaction::Status::TRANSFER_ACCEPTED); + } else { + storage::updateInteractionBody(db, interactionId, acceptedFilePath); + storage::updateInteractionStatus(db, + interactionId, + interaction::Status::TRANSFER_ACCEPTED); + } + // prepare interaction Info and emit signal for the client + auto conversationIdx = indexOf(convUid); + interaction::Info itCopy; + bool emitUpdated = false; + if (conversationIdx != -1) { + std::lock_guard<std::mutex> lk(interactionsLocks[convUid]); + auto& interactions = conversations[conversationIdx].interactions; + auto it = interactions->find(interactionId); + if (it != interactions->end()) { + it->second.body = acceptedFilePath; + it->second.status = interaction::Status::TRANSFER_ACCEPTED; + using namespace MessageList; + interactions->emitDataChanged(it, {Role::Body, Role::Status}); + emitUpdated = true; + itCopy = it->second; + } + } + if (emitUpdated) { + if (conversations[conversationIdx].isCoreDialog()) { + sendContactRequest(peersForConversation(conversations[conversationIdx]).front()); + } + invalidateModel(); + Q_EMIT linked.interactionStatusUpdated(convUid, interactionId, itCopy); + Q_EMIT behaviorController.newReadInteraction(linked.owner.id, convUid, interactionId); + } + return; + } + + auto interaction = conversation.interactions->find(interactionId); + if (interaction != conversation.interactions->end()) { + auto fileId = interaction->second.commit["fileId"]; + if (fileId.isEmpty()) { + qWarning() << "Cannot download file without fileId"; + return; + } + linked.owner.dataTransferModel->download(linked.owner.id, convUid, interactionId, fileId); + } else { + qWarning() << "Cannot download file without valid interaction"; + } +} + +void +ConversationModelPimpl::invalidateModel() +{ + filteredConversations.invalidate(); + customFilteredConversations.invalidate(); +} + +void +ConversationModelPimpl::emplaceBackConversation(conversation::Info&& conversation) +{ + if (indexOf(conversation.uid) != -1) + return; + Q_EMIT linked.beginInsertRows(conversations.size()); + conversations.emplace_back(std::move(conversation)); + Q_EMIT linked.endInsertRows(); +} + +void +ConversationModelPimpl::eraseConversation(const QString& convId) +{ + eraseConversation(indexOf(convId)); +} + +void +ConversationModelPimpl::eraseConversation(int index) +{ + Q_EMIT linked.beginRemoveRows(index); + conversations.erase(conversations.begin() + index); + Q_EMIT linked.endRemoveRows(); +} + +void +ConversationModelPimpl::slotTransferStatusOngoing(const QString& fileId, datatransfer::Info info) +{ + if (info.accountId != linked.owner.id) + return; + QString interactionId; + QString conversationId; + if (not usefulDataFromDataTransfer(fileId, info, interactionId, conversationId)) + return; + bool intUpdated; + + if (!updateTransferStatus(fileId, info, interaction::Status::TRANSFER_ONGOING, intUpdated)) { + return; + } + if (!intUpdated) { + return; + } + auto conversationIdx = indexOf(conversationId); + auto* timer = new QTimer(); + connect(timer, &QTimer::timeout, [=] { + updateTransferProgress(timer, conversationId, conversationIdx, interactionId); + }); + timer->start(1000); +} + +void +ConversationModelPimpl::slotTransferStatusFinished(const QString& fileId, datatransfer::Info info) +{ + if (info.accountId != linked.owner.id) + return; + QString interactionId; + QString conversationId; + if (not usefulDataFromDataTransfer(fileId, info, interactionId, conversationId)) + return; + // prepare interaction Info and emit signal for the client + auto conversationIdx = indexOf(conversationId); + if (conversationIdx != -1) { + bool emitUpdated = false; + auto newStatus = interaction::Status::TRANSFER_FINISHED; + interaction::Info itCopy; + { + std::lock_guard<std::mutex> lk(interactionsLocks[conversationId]); + auto& interactions = conversations[conversationIdx].interactions; + auto it = interactions->find(interactionId); + if (it != interactions->end()) { + // We need to check if current status is ONGOING as CANCELED must not be + // transformed into FINISHED + if (it->second.status == interaction::Status::TRANSFER_ONGOING) { + emitUpdated = true; + it->second.status = newStatus; + interactions->emitDataChanged(it, {MessageList::Role::Status}); + itCopy = it->second; + } + } + } + if (emitUpdated) { + invalidateModel(); + if (conversations[conversationIdx].mode != conversation::Mode::NON_SWARM) { + if (transfIdToDbIntId.find(fileId) != transfIdToDbIntId.end()) { + auto dbIntId = transfIdToDbIntId[fileId]; + storage::updateInteractionStatus(db, dbIntId, newStatus); + } + } else { + storage::updateInteractionStatus(db, interactionId, newStatus); + } + Q_EMIT linked.interactionStatusUpdated(conversationId, interactionId, itCopy); + transfIdToDbIntId.remove(fileId); + } + } +} + +void +ConversationModelPimpl::slotTransferStatusCanceled(const QString& fileId, datatransfer::Info info) +{ + if (info.accountId != linked.owner.id) + return; + bool intUpdated; + updateTransferStatus(fileId, info, interaction::Status::TRANSFER_CANCELED, intUpdated); +} + +void +ConversationModelPimpl::slotTransferStatusError(const QString& fileId, datatransfer::Info info) +{ + if (info.accountId != linked.owner.id) + return; + bool intUpdated; + updateTransferStatus(fileId, info, interaction::Status::TRANSFER_ERROR, intUpdated); +} + +void +ConversationModelPimpl::slotTransferStatusUnjoinable(const QString& fileId, datatransfer::Info info) +{ + if (info.accountId != linked.owner.id) + return; + bool intUpdated; + updateTransferStatus(fileId, info, interaction::Status::TRANSFER_UNJOINABLE_PEER, intUpdated); +} + +void +ConversationModelPimpl::slotTransferStatusTimeoutExpired(const QString& fileId, + datatransfer::Info info) +{ + if (info.accountId != linked.owner.id) + return; + bool intUpdated; + updateTransferStatus(fileId, info, interaction::Status::TRANSFER_TIMEOUT_EXPIRED, intUpdated); +} + +bool +ConversationModelPimpl::updateTransferStatus(const QString& fileId, + datatransfer::Info info, + interaction::Status newStatus, + bool& updated) +{ + QString interactionId; + QString conversationId; + if (not usefulDataFromDataTransfer(fileId, info, interactionId, conversationId)) { + return false; + } + + auto conversationIdx = indexOf(conversationId); + if (conversationIdx < 0) { + return false; + } + auto& conversation = conversations[conversationIdx]; + if (conversation.isLegacy()) { + storage::updateInteractionStatus(db, interactionId, newStatus); + } + bool emitUpdated = false; + interaction::Info itCopy; + { + std::lock_guard<std::mutex> lk(interactionsLocks[conversationId]); + auto& interactions = conversations[conversationIdx].interactions; + auto it = interactions->find(interactionId); + if (it != interactions->end()) { + emitUpdated = true; + VectorInt roles; + it->second.status = newStatus; + roles += MessageList::Role::Status; + if (conversation.isSwarm()) { + it->second.body = info.path; + roles += MessageList::Role::Body; + } + interactions->emitDataChanged(it, roles); + itCopy = it->second; + } + } + if (emitUpdated) { + invalidateModel(); + Q_EMIT linked.interactionStatusUpdated(conversationId, interactionId, itCopy); + } + updated = emitUpdated; + return true; +} + +void +ConversationModelPimpl::updateTransferProgress(QTimer* timer, + const QString& conversation, + int conversationIdx, + const QString& interactionId) +{ + try { + bool emitUpdated = false; + interaction::Info itCopy; + { + auto convId = conversations[conversationIdx].uid; + std::lock_guard<std::mutex> lk(interactionsLocks[convId]); + const auto& interactions = conversations[conversationIdx].interactions; + const auto& it = interactions->find(interactionId); + if (it != interactions->cend() + and it->second.status == interaction::Status::TRANSFER_ONGOING) { + interactions->emitDataChanged(it, {MessageList::Role::Status}); + emitUpdated = true; + itCopy = it->second; + } + } + if (emitUpdated) { + Q_EMIT linked.interactionStatusUpdated(conversation, interactionId, itCopy); + return; + } + } catch (...) { + } + + timer->stop(); + timer->deleteLater(); +} + +} // namespace lrc + +#include "api/moc_conversationmodel.cpp" +#include "conversationmodel.moc" diff --git a/src/libclient/database.cpp b/src/libclient/database.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dec8f1806128cae4bcd146741959be498b39e7b8 --- /dev/null +++ b/src/libclient/database.cpp @@ -0,0 +1,1015 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com> * + * Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com> * + * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#include "database.h" + +#include "api/interaction.h" + +#include <account_const.h> + +// Lrc for migrations +#include "dbus/configurationmanager.h" +#include "vcard.h" +#include <account_const.h> + +#include <QObject> +#include <QtCore/QDir> +#include <QtCore/QDebug> +#include <QtCore/QFile> +#include <QtCore/QJsonArray> +#include <QtCore/QJsonDocument> +#include <QtCore/QJsonObject> +#include <QtSql/QSqlDatabase> +#include <QtSql/QSqlError> +#include <QtSql/QSqlRecord> +#include <QtCore/QVariant> +#include <QDir> +#include <QTextStream> + +#include <sstream> +#include <stdexcept> + +namespace lrc { + +using namespace api; + +Database::Database(const QString& name, const QString& basePath) + : QObject() + , connectionName_(name) + , basePath_(basePath) + , version_(DB_VERSION) +{ + if (not QSqlDatabase::drivers().contains("QSQLITE")) { + throw std::runtime_error("QSQLITE not supported"); + } + + // initalize the database. + db_ = QSqlDatabase::addDatabase("QSQLITE", connectionName_); + + auto databaseFile = QFileInfo(basePath_ + connectionName_ + ".db"); + QString databaseFileName = databaseFile.fileName(); + auto absoluteDir = databaseFile.absoluteDir(); + + // make sure the directory exists + if (!absoluteDir.exists()) + absoluteDir.mkpath("."); + databaseFullPath_ = absoluteDir.filePath(databaseFileName); + + db_.setDatabaseName(databaseFullPath_); +} + +Database::~Database() +{ + close(); +} + +void +Database::close() +{ + // close db + if (db_.isOpen()) { + db_.close(); + } +} + +void +Database::remove() +{ + // close db and remove file + close(); + QFile(databaseFullPath_).remove(); +} + +void +Database::load() +{ + // open the database. + if (not db_.open()) { + std::stringstream ss; + ss << "cannot open database: " << connectionName_.toStdString(); + throw std::runtime_error(ss.str()); + } + + // if db is empty we create them. + if (db_.tables().empty()) { + try { + QSqlDatabase::database(connectionName_).transaction(); + createTables(); + QSqlDatabase::database(connectionName_).commit(); + } catch (QueryError& e) { + QSqlDatabase::database(connectionName_).rollback(); + throw std::runtime_error("Could not correctly create the database"); + } + } else { + migrateIfNeeded(); + } +} + +void +Database::createTables() +{ + QSqlQuery query(db_); + + auto tableConversations = "CREATE TABLE conversations ( \ + id INTEGER, \ + participant TEXT, \ + extra_data TEXT \ + )"; + + auto indexConversations + = "CREATE INDEX `idx_conversations_uri` ON `conversations` (`participant`)"; + + auto tableInteractions = "CREATE TABLE interactions ( \ + id INTEGER PRIMARY KEY, \ + author TEXT, \ + conversation INTEGER, \ + timestamp INTEGER, \ + body TEXT, \ + type TEXT, \ + status TEXT, \ + is_read INTEGER, \ + daemon_id BIGINT, \ + extra_data TEXT, \ + FOREIGN KEY(conversation) REFERENCES conversations(id) \ + )"; + + auto indexInteractions = "CREATE INDEX `idx_interactions_uri` ON `interactions` (`author`)"; + + // add conversations table + if (!db_.tables().contains("conversations", Qt::CaseInsensitive)) { + if (!query.exec(tableConversations) || !query.exec(indexConversations)) { + throw QueryError(std::move(query)); + } + } + + // add interactions table + if (!db_.tables().contains("interactions", Qt::CaseInsensitive)) { + if (!query.exec(tableInteractions) || !query.exec(indexInteractions)) { + throw QueryError(std::move(query)); + } + } + + storeVersion(version_); +} + +void +Database::migrateIfNeeded() +{ + try { + auto currentVersion = getVersion(); + if (currentVersion == version_) { + return; + } + QSqlDatabase::database().transaction(); + migrateFromVersion(currentVersion); + storeVersion(version_); + QSqlDatabase::database().commit(); + } catch (QueryError& e) { + QSqlDatabase::database().rollback(); + throw std::runtime_error("Could not correctly migrate the database"); + } +} + +void +Database::migrateFromVersion(const QString& currentVersion) +{ + (void) currentVersion; +} + +void +Database::storeVersion(const QString& version) +{ + QSqlQuery query(db_); + + auto storeVersionQuery = "PRAGMA user_version = " + version; + + if (not query.exec(storeVersionQuery)) + throw QueryError(std::move(query)); + + qDebug() << "database " << databaseFullPath_ << " version set to:" << version; +} + +QString +Database::getVersion() +{ + QSqlQuery query(db_); + auto getVersionQuery = "pragma user_version"; + if (not query.exec(getVersionQuery)) + throw QueryError(std::move(query)); + query.first(); + return query.value(0).toString(); +} + +QString +Database::insertInto( + const QString& table, // "tests" + const MapStringString& + bindCol, // {{":id", "id"}, {":forename", "colforname"}, {":name", "colname"}} + const MapStringString& bindsSet) // {{":id", "7"}, {":forename", "alice"}, {":name", "cooper"}} +{ + QSqlQuery query(db_); + QString columns; + QString binds; + + for (const auto& entry : bindCol.toStdMap()) { + columns += entry.second + ","; + binds += entry.first + ","; + } + + // remove the last ',' + columns.chop(1); + binds.chop(1); + + auto prepareStr = "INSERT INTO " + table + " (" + columns + ") VALUES (" + binds + ")"; + query.prepare(prepareStr); + + for (const auto& entry : bindsSet.toStdMap()) + query.bindValue(entry.first, entry.second); + + if (not query.exec()) + throw QueryInsertError(std::move(query), table, bindCol, bindsSet); + + if (not query.exec("SELECT last_insert_rowid()")) + throw QueryInsertError(std::move(query), table, bindCol, bindsSet); + + if (!query.next()) + return QString::number(-1); + ; + + return query.value(0).toString(); +} + +void +Database::update(const QString& table, // "tests" + const QString& set, // "location=:place, phone:=nmbr" + const MapStringString& bindsSet, // {{":place", "montreal"}, {":nmbr", "514"}} + const QString& where, // "contact=:name AND id=:id + const MapStringString& bindsWhere) // {{":name", "toto"}, {":id", "65"}} +{ + QSqlQuery query(db_); + + auto prepareStr = QString("UPDATE " + table + " SET " + set + " WHERE " + where); + query.prepare(prepareStr); + + for (const auto& entry : bindsSet.toStdMap()) + query.bindValue(entry.first, entry.second); + + for (const auto& entry : bindsWhere.toStdMap()) + query.bindValue(entry.first, entry.second); + + if (not query.exec()) + throw QueryUpdateError(std::move(query), table, set, bindsSet, where, bindsWhere); +} + +Database::Result +Database::select(const QString& select, // "id", "body", ... + const QString& table, // "tests" + const QString& where, // "contact=:name AND id=:id + const MapStringString& bindsWhere) // {{":name", "toto"}, {":id", "65"}} +{ + QSqlQuery query(db_); + QString columnsSelect; + + auto prepareStr = QString("SELECT " + select + " FROM " + table + + (where.isEmpty() ? "" : (" WHERE " + where))); + query.prepare(prepareStr); + + for (const auto& entry : bindsWhere.toStdMap()) + query.bindValue(entry.first, entry.second); + + if (not query.exec()) + throw QuerySelectError(std::move(query), select, table, where, bindsWhere); + + QSqlRecord rec = query.record(); + const auto col_num = rec.count(); + Database::Result result = {col_num, {}}; + + // for each row + while (query.next()) { + for (int i = 0; i < col_num; i++) + result.payloads.push_back(query.value(i).toString()); + } + + return result; +} + +int +Database::count(const QString& count, // "id", "body", ... + const QString& table, // "tests" + const QString& where, // "contact=:name AND id=:id" + const MapStringString& bindsWhere) // {{":name", "toto"}, {":id", "65"}} +{ + QSqlQuery query(db_); + QString columnsSelect; + auto prepareStr = QString("SELECT count(" + count + ") FROM " + table + " WHERE " + where); + query.prepare(prepareStr); + + for (const auto& entry : bindsWhere.toStdMap()) + query.bindValue(entry.first, entry.second); + + if (not query.exec()) + throw QueryError(std::move(query)); + + query.next(); + return query.value(0).toInt(); +} + +void +Database::deleteFrom(const QString& table, // "tests" + const QString& where, // "contact=:name AND id=:id + const MapStringString& bindsWhere) // {{":name", "toto"}, {":id", "65"}} +{ + QSqlQuery query(db_); + + auto prepareStr = QString("DELETE FROM " + table + " WHERE " + where); + query.prepare(prepareStr); + + for (const auto& entry : bindsWhere.toStdMap()) + query.bindValue(entry.first, entry.second); + + if (not query.exec()) + throw QueryDeleteError(std::move(query), table, where, bindsWhere); +} + +Database::QueryError::QueryError(QSqlQuery&& query) + : std::runtime_error(query.lastError().text().toStdString()) + , query(std::move(query)) +{} + +Database::QueryInsertError::QueryInsertError(QSqlQuery&& query, + const QString& table, + const MapStringString& bindCol, + const MapStringString& bindsSet) + : QueryError(std::move(query)) + , table(table) + , bindCol(bindCol) + , bindsSet(bindsSet) +{} + +QString +Database::QueryInsertError::details() +{ + QTextStream qts; + qts << "parameters sent :"; + qts << "table = " << table; + for (auto& b : bindCol.toStdMap()) + qts << " {" << b.first << "}, {" << b.second << "}"; + for (auto& b : bindsSet.toStdMap()) + qts << " {" << b.first << "}, {" << b.second << "}"; + return qts.readAll(); +} + +Database::QueryUpdateError::QueryUpdateError(QSqlQuery&& query, + const QString& table, + const QString& set, + const MapStringString& bindsSet, + const QString& where, + const MapStringString& bindsWhere) + : QueryError(std::move(query)) + , table(table) + , set(set) + , bindsSet(bindsSet) + , where(where) + , bindsWhere(bindsWhere) +{} + +QString +Database::QueryUpdateError::details() +{ + QTextStream qts; + qts << "parameters sent :"; + qts << "table = " << table; + qts << "set = " << set; + qts << "bindsSet :"; + for (auto& b : bindsSet.toStdMap()) + qts << " {" << b.first << "}, {" << b.second << "}"; + qts << "where = " << where; + qts << "bindsWhere :"; + for (auto& b : bindsWhere.toStdMap()) + qts << " {" << b.first << "}, {" << b.second << "}"; + return qts.readAll(); +} + +Database::QuerySelectError::QuerySelectError(QSqlQuery&& query, + const QString& select, + const QString& table, + const QString& where, + const MapStringString& bindsWhere) + : QueryError(std::move(query)) + , select(select) + , table(table) + , where(where) + , bindsWhere(bindsWhere) +{} + +QString +Database::QuerySelectError::details() +{ + QTextStream qts; + qts << "parameters sent :"; + qts << "select = " << select; + qts << "table = " << table; + qts << "where = " << where; + qts << "bindsWhere :"; + for (auto& b : bindsWhere.toStdMap()) + qts << " {" << b.first << "}, {" << b.second << "}"; + return qts.readAll(); +} + +Database::QueryDeleteError::QueryDeleteError(QSqlQuery&& query, + const QString& table, + const QString& where, + const MapStringString& bindsWhere) + : QueryError(std::move(query)) + , table(table) + , where(where) + , bindsWhere(bindsWhere) +{} + +QString +Database::QueryDeleteError::details() +{ + QTextStream qts; + qts << "parameters sent :"; + qts << "table = " << table; + qts << "where = " << where; + qts << "bindsWhere :"; + for (auto& b : bindsWhere.toStdMap()) + qts << " {" << b.first << "}, {" << b.second << "}"; + return qts.readAll(); +} + +Database::QueryTruncateError::QueryTruncateError(QSqlQuery&& query, const QString& table) + : QueryError(std::move(query)) + , table(table) +{} + +QString +Database::QueryTruncateError::details() +{ + QTextStream qts; + qts << "parameters sent :"; + qts << "table = " << table; + return qts.readAll(); +} + +/***************************************************************************** + * * + * LegacyDatabase * + * * + ****************************************************************************/ +LegacyDatabase::LegacyDatabase(const QString& basePath) + : Database("ring", basePath) +{ + version_ = LEGACY_DB_VERSION; +} + +LegacyDatabase::~LegacyDatabase() +{ + remove(); + // remove old LRC files + QDir(basePath_ + "text/").removeRecursively(); + QDir(basePath_ + "profiles/").removeRecursively(); + QDir(basePath_ + "peer_profiles/").removeRecursively(); +} + +void +LegacyDatabase::load() +{ + // open the database. + if (not db_.open()) { + std::stringstream ss; + ss << "cannot open database: " << connectionName_.toStdString(); + throw std::runtime_error(ss.str()); + } + + // if db is empty we create them. + if (db_.tables().empty()) { + try { + QSqlDatabase::database(connectionName_).transaction(); + createTables(); + QSqlDatabase::database(connectionName_).commit(); + } catch (QueryError& e) { + QSqlDatabase::database(connectionName_).rollback(); + throw std::runtime_error("Could not correctly create the database"); + } + migrateOldFiles(); + } else { + migrateIfNeeded(); + } +} + +void +LegacyDatabase::createTables() +{ + QSqlQuery query(db_); + + auto tableProfiles = "CREATE TABLE profiles (id INTEGER PRIMARY KEY, \ + uri TEXT NOT NULL, \ + alias TEXT, \ + photo TEXT, \ + type TEXT, \ + status TEXT)"; + + auto tableConversations = "CREATE TABLE conversations (id INTEGER,\ + participant_id INTEGER, \ + FOREIGN KEY(participant_id) REFERENCES profiles(id))"; + + auto tableInteractions = "CREATE TABLE interactions (id INTEGER PRIMARY KEY,\ + account_id INTEGER, \ + author_id INTEGER, \ + conversation_id INTEGER, \ + timestamp INTEGER, \ + body TEXT, \ + type TEXT, \ + status TEXT, \ + daemon_id TEXT, \ + FOREIGN KEY(account_id) REFERENCES profiles(id), \ + FOREIGN KEY(author_id) REFERENCES profiles(id), \ + FOREIGN KEY(conversation_id) REFERENCES conversations(id))"; + + auto tableProfileAccounts + = "CREATE TABLE profiles_accounts (profile_id INTEGER NOT NULL, \ + account_id TEXT NOT NULL, \ + is_account TEXT, \ + FOREIGN KEY(profile_id) REFERENCES profiles(id))"; + // add profiles table + if (not db_.tables().contains("profiles", Qt::CaseInsensitive) + and not query.exec(tableProfiles)) { + throw QueryError(std::move(query)); + } + + // add conversations table + if (not db_.tables().contains("conversations", Qt::CaseInsensitive) + and not query.exec(tableConversations)) { + throw QueryError(std::move(query)); + } + + // add interactions table + if (not db_.tables().contains("interactions", Qt::CaseInsensitive) + and not query.exec(tableInteractions)) { + throw QueryError(std::move(query)); + } + + // add profiles accounts table + if (not db_.tables().contains("profiles_accounts", Qt::CaseInsensitive) + and not query.exec(tableProfileAccounts)) { + throw QueryError(std::move(query)); + } + + storeVersion(version_); +} + +void +LegacyDatabase::migrateOldFiles() +{ + migrateLocalProfiles(); + migratePeerProfiles(); + migrateTextHistory(); + linkRingProfilesWithAccounts(true); +} + +void +LegacyDatabase::migrateLocalProfiles() +{ + const QDir profilesDir = basePath_ + "profiles/"; + const QStringList entries = profilesDir.entryList({QStringLiteral("*.vcf")}, QDir::Files); + Q_FOREACH (const QString& item, entries) { + auto filePath = profilesDir.path() + '/' + item; + QString content; + QFile file(filePath); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + content = QString::fromUtf8(file.readAll()); + } else { + qWarning() << "Could not open .vcf file"; + continue; + } + + const auto vCard = lrc::vCard::utils::toHashMap(content.toUtf8()); + const auto alias = vCard[lrc::vCard::Property::FORMATTED_NAME]; + const auto avatar = vCard["PHOTO;ENCODING=BASE64;TYPE=PNG"]; + + const QStringList accountIds = ConfigurationManager::instance().getAccountList(); + for (auto accountId : accountIds) { + // NOTE: If the daemon is down, but dbus answered, id can contains + // "Remote peer disconnected", "The name is not activable", etc. + // So avoid to migrate useless directories. + for (auto& id : accountIds) + if (id.indexOf(" ") != -1) { + qWarning() << "Invalid dbus answer. Daemon not running"; + return; + } + MapStringString account = ConfigurationManager::instance().getAccountDetails( + accountId.toStdString().c_str()); + auto accountURI = account[DRing::Account::ConfProperties::USERNAME].contains("ring:") + ? account[DRing::Account::ConfProperties::USERNAME] + .toStdString() + .substr(std::string("ring:").size()) + : account[DRing::Account::ConfProperties::USERNAME].toStdString(); + + for (const auto& accountId : accountIds) { + MapStringString account = ConfigurationManager::instance().getAccountDetails( + accountId.toStdString().c_str()); + auto type = account[DRing::Account::ConfProperties::TYPE] == "SIP" ? "SIP" : "RING"; + + auto uri = account[DRing::Account::ConfProperties::USERNAME].contains("ring:") + ? QString(account[DRing::Account::ConfProperties::USERNAME]) + .remove(0, QString("ring:").size()) + : account[DRing::Account::ConfProperties::USERNAME]; + if (select("id", "profiles", "uri=:uri", {{":uri", uri}}).payloads.empty()) { + insertInto("profiles", + {{":uri", "uri"}, + {":alias", "alias"}, + {":photo", "photo"}, + {":type", "type"}, + {":status", "status"}}, + {{":uri", uri}, + {":alias", alias}, + {":photo", avatar}, + {":type", type}, + {":status", "TRUSTED"}}); + auto profileIds = select("id", "profiles", "uri=:uri", {{":uri", uri}}).payloads; + if (!profileIds.empty() + && select("profile_id", + "profiles_accounts", + "account_id=:account_id AND is_account=:is_account", + {{":account_id", accountId}, {":is_account", "true"}}) + .payloads.empty()) { + insertInto("profiles_accounts", + {{":profile_id", "profile_id"}, + {":account_id", "account_id"}, + {":is_account", "is_account"}}, + {{":profile_id", profileIds[0]}, + {":account_id", accountId}, + {":is_account", "true"}}); + } + } + } + } + } +} + +void +LegacyDatabase::migratePeerProfiles() +{ + const QDir profilesDir = basePath_ + "peer_profiles/"; + + const QStringList entries = profilesDir.entryList({QStringLiteral("*.vcf")}, QDir::Files); + + Q_FOREACH (const QString& item, entries) { + auto filePath = profilesDir.path() + '/' + item; + QString content; + QFile file(filePath); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + content = QString::fromUtf8(file.readAll()); + } else { + qWarning() << "Could not open vcf file"; + continue; + } + + const auto vCard = lrc::vCard::utils::toHashMap(content.toUtf8()); + auto uri = vCard["TEL;other"]; + const auto alias = vCard["FN"]; + const auto avatar = vCard["PHOTO;ENCODING=BASE64;TYPE=PNG"]; + const QString type = uri.startsWith("ring:") ? "RING" : "SIP"; + if (uri.startsWith("ring:")) { + uri = uri.mid(QString("ring:").size()); + } + + if (select("id", "profiles", "uri=:uri", {{":uri", uri}}).payloads.empty()) { + insertInto("profiles", + {{":uri", "uri"}, + {":alias", "alias"}, + {":photo", "photo"}, + {":type", "type"}, + {":status", "status"}}, + {{":uri", uri}, + {":alias", alias}, + {":photo", avatar}, + {":type", type}, + {":status", "TRUSTED"}}); + } + } +} + +void +LegacyDatabase::migrateTextHistory() +{ + // load all text recordings so we can recover CMs that are not in the call history + QDir dir(basePath_ + "text/"); + if (dir.exists()) { + // get .json files, sorted by time, latest first + QStringList filters; + filters << "*.json"; + auto list = dir.entryInfoList(filters, + QDir::Files | QDir::NoSymLinks | QDir::Readable, + QDir::Time); + + for (int i = 0; i < list.size(); ++i) { + QFileInfo fileInfo = list.at(i); + + QString content; + QFile file(fileInfo.absoluteFilePath()); + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + content = QString::fromUtf8(file.readAll()); + } else { + qWarning() << "Could not open text recording json file"; + continue; + } + + if (!content.isEmpty()) { + QJsonParseError err; + auto loadDoc = QJsonDocument::fromJson(content.toUtf8(), &err).object(); + + if (loadDoc.find("peers") == loadDoc.end()) + continue; + if (loadDoc.find("groups") == loadDoc.end()) + continue; + // Load account + auto peersObject = loadDoc["peers"].toArray()[0].toObject(); + + MapStringString details = ConfigurationManager::instance().getAccountDetails( + peersObject["accountId"].toString()); + if (!details.contains(DRing::Account::ConfProperties::USERNAME)) + continue; + + auto accountUri = details[DRing::Account::ConfProperties::USERNAME]; + auto isARingContact = accountUri.startsWith("ring:"); + if (isARingContact) { + accountUri = accountUri.mid(QString("ring:").length()); + } + auto accountIds = select("id", "profiles", "uri=:uri", {{":uri", accountUri}}) + .payloads; + auto contactIds = select("id", + "profiles", + "uri=:uri", + {{":uri", peersObject["uri"].toString()}}) + .payloads; + if (contactIds.empty()) { + insertInto("profiles", + {{":uri", "uri"}, + {":alias", "alias"}, + {":photo", "photo"}, + {":type", "type"}, + {":status", "status"}}, + {{":uri", peersObject["uri"].toString()}, + {":alias", ""}, + {":photo", ""}, + {":type", "RING"}, + {":status", "TRUSTED"}}); + // NOTE: this profile is in a case where it's not a contact for the daemon but a + // conversation with an account. So we choose to add the profile to daemon's contacts + if (isARingContact) { + ConfigurationManager::instance() + .addContact(peersObject["accountId"].toString(), + peersObject["uri"].toString()); + } + contactIds = select("id", + "profiles", + "uri=:uri", + {{":uri", peersObject["uri"].toString()}}) + .payloads; + } + if (accountIds.empty()) { + qDebug() << "Can't find profile for URI: " + << peersObject["accountId"].toString() << ". Ignore this file."; + } else if (contactIds.empty()) { + qDebug() << "Can't find profile for URI: " << peersObject["uri"].toString() + << ". Ignore this file."; + } else { + auto contactId = contactIds[0]; + // link profile id to account id + auto profiles = select("profile_id", + "profiles_accounts", + "profile_id=:profile_id AND \ + account_id=:account_id AND \ + is_account=:is_account", + {{":profile_id", contactId}, + {":account_id", peersObject["accountId"].toString()}, + {":is_account", "false"}}) + .payloads; + + if (profiles.empty()) { + insertInto("profiles_accounts", + {{":profile_id", "profile_id"}, + {":account_id", "account_id"}, + {":is_account", "is_account"}}, + {{":profile_id", contactId}, + {":account_id", peersObject["accountId"].toString()}, + {":is_account", "false"}}); + } + auto accountId = accountIds[0]; + auto newConversationsId + = select("IFNULL(MAX(id), 0) + 1", "conversations", "1=1", {}).payloads[0]; + try { + QSqlDatabase::database().transaction(); + insertInto("conversations", + {{":id", "id"}, {":participant_id", "participant_id"}}, + {{":id", newConversationsId}, {":participant_id", accountId}}); + insertInto("conversations", + {{":id", "id"}, {":participant_id", "participant_id"}}, + {{":id", newConversationsId}, {":participant_id", contactId}}); + QSqlDatabase::database().commit(); + } catch (QueryInsertError& e) { + qDebug() << e.details(); + QSqlDatabase::database().rollback(); + } + + // Load interactions + auto groupsArray = loadDoc["groups"].toArray(); + for (const auto& groupObject : groupsArray) { + auto messagesArray = groupObject.toObject()["messages"].toArray(); + for (const auto& messageRef : messagesArray) { + auto messageObject = messageRef.toObject(); + auto direction = messageObject["direction"].toInt(); + auto body = messageObject["payloads"] + .toArray()[0] + .toObject()["payload"] + .toString(); + insertInto("interactions", + {{":account_id", "account_id"}, + {":author_id", "author_id"}, + {":conversation_id", "conversation_id"}, + {":timestamp", "timestamp"}, + {":body", "body"}, + {":type", "type"}, + {":status", "status"}}, + {{":account_id", accountId}, + {":author_id", direction ? accountId : contactId}, + {":conversation_id", newConversationsId}, + {":timestamp", messageObject["timestamp"].toString()}, + {":body", body}, + {":type", "TEXT"}, + {":status", direction ? "SUCCEED" : "READ"}}); + } + } + } + } else { + qWarning() << "Text recording file is empty"; + } + } + } +} + +void +LegacyDatabase::migrateFromVersion(const QString& currentVersion) +{ + if (currentVersion == "1") { + migrateSchemaFromVersion1(); + } +} + +void +LegacyDatabase::migrateSchemaFromVersion1() +{ + QSqlQuery query(db_); + auto tableProfileAccounts + = "CREATE TABLE profiles_accounts (profile_id INTEGER NOT NULL, \ + account_id TEXT NOT NULL, \ + is_account TEXT, \ + FOREIGN KEY(profile_id) REFERENCES profiles(id))"; + // add profiles accounts table + if (not db_.tables().contains("profiles_accounts", Qt::CaseInsensitive) + and not query.exec(tableProfileAccounts)) { + throw QueryError(std::move(query)); + } + linkRingProfilesWithAccounts(false); +} + +void +LegacyDatabase::linkRingProfilesWithAccounts(bool contactsOnly) +{ + const QStringList accountIds = ConfigurationManager::instance().getAccountList(); + for (auto accountId : accountIds) { + // NOTE: If the daemon is down, but dbus answered, id can contains + // "Remote peer disconnected", "The name is not activable", etc. + // So avoid to migrate useless directories. + for (auto& id : accountIds) + if (id.indexOf(" ") != -1) { + qWarning() << "Invalid dbus answer. Daemon not running"; + return; + } + MapStringString account = ConfigurationManager::instance().getAccountDetails( + accountId.toStdString().c_str()); + auto accountURI = account[DRing::Account::ConfProperties::USERNAME].contains("ring:") + ? QString(account[DRing::Account::ConfProperties::USERNAME]) + .remove(0, QString("ring:").size()) + : account[DRing::Account::ConfProperties::USERNAME]; + auto profileIds = select("id", "profiles", "uri=:uri", {{":uri", accountURI}}).payloads; + if (profileIds.empty()) { + continue; + } + if (!contactsOnly) { + // if is_account is true we should have only one profile id for account id + if (select("profile_id", + "profiles_accounts", + "account_id=:account_id AND is_account=:is_account", + {{":account_id", accountId}, {":is_account", "true"}}) + .payloads.empty()) { + insertInto("profiles_accounts", + {{":profile_id", "profile_id"}, + {":account_id", "account_id"}, + {":is_account", "is_account"}}, + {{":profile_id", profileIds[0]}, + {":account_id", accountId}, + {":is_account", "true"}}); + } + } + + if (account[DRing::Account::ConfProperties::TYPE] == DRing::Account::ProtocolNames::RING) { + // update RING contacts + const VectorMapStringString& contacts_vector + = ConfigurationManager::instance().getContacts(accountId.toStdString().c_str()); + // update contacts profiles + for (auto contact_info : contacts_vector) { + auto contactURI = contact_info["id"]; + updateProfileAccountForContact(contactURI, accountId); + } + // update pending contacts profiles + const VectorMapStringString& pending_tr + = ConfigurationManager::instance().getTrustRequests(accountId.toStdString().c_str()); + for (auto tr_info : pending_tr) { + auto contactURI = tr_info[DRing::Account::TrustRequest::FROM]; + updateProfileAccountForContact(contactURI, accountId); + } + } else if (account[DRing::Account::ConfProperties::TYPE] + == DRing::Account::ProtocolNames::SIP) { + // update SIP contacts + auto conversations = select("id", + "conversations", + "participant_id=:participant_id", + {{":participant_id", profileIds[0]}}) + .payloads; + for (const auto& c : conversations) { + auto otherParticipants = select("participant_id", + "conversations", + "id=:id AND participant_id!=:participant_id", + {{":id", c}, {":participant_id", profileIds[0]}}) + .payloads; + for (const auto& participant : otherParticipants) { + auto rows = select("profile_id", + "profiles_accounts", + "profile_id=:profile_id AND \ + account_id=:account_id AND \ + is_account=:is_account", + {{":profile_id", participant}, + {":account_id", accountId}, + {":is_account", "false"}}) + .payloads; + if (rows.empty()) { + insertInto("profiles_accounts", + {{":profile_id", "profile_id"}, + {":account_id", "account_id"}, + {":is_account", "is_account"}}, + {{":profile_id", participant}, + {":account_id", accountId}, + {":is_account", "false"}}); + } + } + } + } + } +} + +void +LegacyDatabase::updateProfileAccountForContact(const QString& contactURI, const QString& accountId) +{ + auto profileIds = select("id", "profiles", "uri=:uri", {{":uri", contactURI}}).payloads; + if (profileIds.empty()) { + return; + } + auto rows = select("profile_id", + "profiles_accounts", + "account_id=:account_id AND is_account=:is_account", + {{":account_id", accountId}, {":is_account", "false"}}) + .payloads; + if (std::find(rows.begin(), rows.end(), profileIds[0]) == rows.end()) { + insertInto("profiles_accounts", + {{":profile_id", "profile_id"}, + {":account_id", "account_id"}, + {":is_account", "is_account"}}, + {{":profile_id", profileIds[0]}, + {":account_id", accountId}, + {":is_account", "false"}}); + } +} + +} // namespace lrc diff --git a/src/libclient/database.h b/src/libclient/database.h new file mode 100644 index 0000000000000000000000000000000000000000..05cc1c85bcb2700a1981e17308dfd784c20cc430 --- /dev/null +++ b/src/libclient/database.h @@ -0,0 +1,337 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com> * + * Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com> * + * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#include "typedefs.h" + +// Qt +#include <QObject> +#include <QtCore/QDir> +#include <QtSql/QSqlQuery> +#include <QtCore/QStandardPaths> +#include <QDebug> + +// Std +#include <memory> +#include <string> +#include <stdexcept> +#include <type_traits> + +namespace lrc { + +static constexpr auto LEGACY_DB_VERSION = "1.1"; +static constexpr auto DB_VERSION = "1"; + +/** + * @brief Base class that communicates with a database. + * @note not thread safe. + */ +class Database : public QObject +{ + Q_OBJECT + +public: + /** + * Create a database on the user system. + * @param the name for which to construct the db. + * @exception QueryError database query error. + */ + Database(const QString& name, const QString& basePath); + ~Database(); + + void remove(); + + void close(); + + virtual void load(); + + /** + * A structure which contains result(s) returned by a database query. + */ + struct Result + { + int nbrOfCols = -1; ///< store the number of columns returned. + /** + * if nbrOfCols equals three and if the size of payloads equals six, + * means two rows of data over three columns. + */ + VectorString payloads; ///< store the values. + }; + + /** + * Generic database query exception. + * details() returns more information, could be empty. + */ + class QueryError : public std::runtime_error + { + public: + explicit QueryError(QSqlQuery&& query); + virtual QString details() { return {}; } + + const QSqlQuery query; + }; + + /** + * Exception on database insert operation. + * details() returns more information. + */ + class QueryInsertError final : public QueryError + { + public: + explicit QueryInsertError(QSqlQuery&& query, + const QString& table, + const MapStringString& bindCol, + const MapStringString& bindsSet); + QString details() override; + + const QString table; + const MapStringString bindCol; + const MapStringString bindsSet; + }; + + /** + * Exception on database update operation. + * details() returns more information. + */ + class QueryUpdateError final : public QueryError + { + public: + explicit QueryUpdateError(QSqlQuery&& query, + const QString& table, + const QString& set, + const MapStringString& bindsSet, + const QString& where, + const MapStringString& bindsWhere); + QString details() override; + + const QString table; + const QString set; + const MapStringString bindsSet; + const QString where; + const MapStringString bindsWhere; + }; + + /** + * Exception on database select operation. + * details() returns more information. + */ + class QuerySelectError final : public QueryError + { + public: + explicit QuerySelectError(QSqlQuery&& query, + const QString& select, + const QString& table, + const QString& where, + const MapStringString& bindsWhere); + QString details() override; + + const QString select; + const QString table; + const QString where; + const MapStringString bindsWhere; + }; + + /** + * Exception on database delete operation. + * details() returns more information. + */ + class QueryDeleteError final : public QueryError + { + public: + explicit QueryDeleteError(QSqlQuery&& query, + const QString& table, + const QString& where, + const MapStringString& bindsWhere); + QString details() override; + + const QString table; + const QString where; + const MapStringString bindsWhere; + }; + + /** + * Exception on database truncate operation. + * details() returns more information. + */ + class QueryTruncateError final : public QueryError + { + public: + explicit QueryTruncateError(QSqlQuery&& query, const QString& table); + QString details() override; + + const QString table; + }; + + /** + * Insert value(s) inside a table. + * @param table where to perfom the action on. + * @param bindCol binds column(s) and identifier(s). The key is the identifier, it should begin + * by ':'. The value is the name of the column from the table. + * @param bindsSet binds value(s) and identifier(s). The key is the identifier, it should begin + * by ':'. The value is the value to store. + * @return qstring from signed integer representing the index of last inserted element. -1 if + * nothing inserted. + * @exception QueryInsertError insert query failed. + * + * @note usually the identifiers has to be the same between bindCol and bindsSet + */ + QString insertInto(const QString& table, + const MapStringString& bindCol, + const MapStringString& bindsSet); + /** + * Update value(s) inside a table. + * @param table where to perfom the action on. + * @param set defines which column(s), using identifier(s), will be updated. + * @param bindsSet specifies the value(s) to set, using the identifier(s). The key is the + * identifier, it should begin by ':'. The value is value to set. + * @param where defines the conditional to update, using identifier(s). + * @param bindsWhere specifies the value(s) to test using the identifier(s). The key is the + * identifier, it should begin by ':'. The value is the value test. + * @exception QueryUpdateError update query failed. + * + * @note usually, identifiers between set and bindsSet, are equals. The same goes between where + * and bindsWhere. + */ + void update(const QString& table, + const QString& set, + const MapStringString& bindsSet, + const QString& where, + const MapStringString& bindsWhere); + /** + * Delete rows from a table. + * @param table where to perfom the action on. + * @param where defines the conditional to update, using identifier(s). + * @param bindsWhere specifies the value(s) to test using the identifier(s). The key is the + * identifier, it should begin by ':'. The value is the value test. + * @exception QueryDeleteError delete query failed. + * + * @note usually, identifiers between where and bindsWhere, are equals. + */ + void deleteFrom(const QString& table, const QString& where, const MapStringString& bindsWhere); + /** + * Select data from table. + * @param select column(s) to select.e + * @param table where to perfom the action on. + * @param where defines the conditional to select, using identifier(s). + * @param bindsWhere specifies the value(s) to test using the identifier(s). The key is the + * identifier, it should begin by ':'. The value is the value to test. + * @return Database::Result which contains the result(s). + * @exception QuerySelectError select query failed. + * + * @note usually, identifiers between where and bindsWhere, are equals. + */ + Database::Result select(const QString& select, + const QString& table, + const QString& where, + const MapStringString& bindsWhere); + + /** + * Returns the count of an expression. + * @param count is the column to count. + * @param table where to perfom the action on. + * @param where defines the conditional to select using identifiers + * @param bindsWhere specifies the value(s) to test using the identifier(s). The key is the + * identifier, it should begin by ':'. The value is the value to test. + */ + int count(const QString& count, + const QString& table, + const QString& where, + const MapStringString& bindsWhere); + + QString basePath_; + +protected: + virtual void createTables(); + + /** + * Migration helpers. + */ + void migrateIfNeeded(); + void storeVersion(const QString& version); + QString getVersion(); + + virtual void migrateFromVersion(const QString& version); + + QString version_; + QString connectionName_; + QString databaseFullPath_; + QSqlDatabase db_; +}; + +/** + * @brief A legacy database to help migrate from the single db epoch. + * @note not thread safe. + */ +class LegacyDatabase final : public Database +{ + Q_OBJECT + +public: + /** + * Create a migratory legacy database. + * @exception QueryError database query error. + */ + LegacyDatabase(const QString& basePath); + ~LegacyDatabase(); + + void load() override; + +protected: + void createTables() override; + +private: + /** + * Migration helpers from old LRC. Parse JSON for history and VCards and add it into the database. + */ + void migrateOldFiles(); + void migrateLocalProfiles(); + void migratePeerProfiles(); + void migrateTextHistory(); + + void migrateFromVersion(const QString& version) override; + + /** + * Migration helpers from version 1 + */ + void migrateSchemaFromVersion1(); + void linkRingProfilesWithAccounts(bool contactsOnly); + void updateProfileAccountForContact(const QString& contactURI, const QString& accountID); +}; + +namespace DatabaseFactory { +template<typename T, class... Args> +std::enable_if_t<std::is_constructible<T, Args...>::value, std::shared_ptr<Database>> +create(Args&&... args) +{ + auto pdb = std::static_pointer_cast<Database>(std::make_shared<T>(std::forward<Args>(args)...)); + // To allow override of the db load method we don't + // call it from the constructor. + try { + pdb->load(); + } catch (const std::runtime_error& e) { + throw std::runtime_error(e); + } + return pdb; +} +} // namespace DatabaseFactory + +} // namespace lrc diff --git a/src/libclient/datatransfermodel.cpp b/src/libclient/datatransfermodel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0360b12f53cd0b08215c3561c5a214fb98564fea --- /dev/null +++ b/src/libclient/datatransfermodel.cpp @@ -0,0 +1,290 @@ +/**************************************************************************** + * Copyright (C) 2018-2022 Savoir-faire Linux Inc. * + * Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +// LRC +#include "api/datatransfermodel.h" + +// Dbus +#include "dbus/configurationmanager.h" + +// DRing +#include <datatransfer_interface.h> + +// Std +#include <map> +#include <stdexcept> +#include <type_traits> + +// Qt +#include <QDir> +#include <QFileInfo> +#include <QtCore/QStandardPaths> +#include <QUuid> + +namespace lrc { +namespace api { + +// DRING to LRC event code conversion +static inline datatransfer::Status +convertDataTransferEvent(DRing::DataTransferEventCode event) +{ + switch (event) { + case DRing::DataTransferEventCode::invalid: + return datatransfer::Status::INVALID; + case DRing::DataTransferEventCode::created: + return datatransfer::Status::on_connection; + case DRing::DataTransferEventCode::unsupported: + return datatransfer::Status::unsupported; + case DRing::DataTransferEventCode::wait_peer_acceptance: + return datatransfer::Status::on_connection; + case DRing::DataTransferEventCode::wait_host_acceptance: + return datatransfer::Status::on_connection; + case DRing::DataTransferEventCode::ongoing: + return datatransfer::Status::on_progress; + case DRing::DataTransferEventCode::finished: + return datatransfer::Status::success; + case DRing::DataTransferEventCode::closed_by_host: + return datatransfer::Status::stop_by_host; + case DRing::DataTransferEventCode::closed_by_peer: + return datatransfer::Status::stop_by_peer; + case DRing::DataTransferEventCode::invalid_pathname: + return datatransfer::Status::invalid_pathname; + case DRing::DataTransferEventCode::unjoinable_peer: + return datatransfer::Status::unjoinable_peer; + case DRing::DataTransferEventCode::timeout_expired: + return datatransfer::Status::timeout_expired; + } + throw std::runtime_error("BUG: broken convertDataTransferEvent() switch"); +} + +class DataTransferModel::Impl : public QObject +{ + Q_OBJECT + +public: + Impl(DataTransferModel& up_link); + + QString getUniqueFilePath(const QString& filename, const QString& path = ""); + + DataTransferModel& upLink; + MapStringString file2InteractionId; + MapStringString interactionToFileId; // stricly the reverse map of file2InteractionId +}; + +DataTransferModel::Impl::Impl(DataTransferModel& up_link) + : QObject {} + , upLink {up_link} +{} + +QString +DataTransferModel::Impl::getUniqueFilePath(const QString& filename, const QString& path) +{ + auto base = filename; + QString ext = QFileInfo(base).completeSuffix(); + if (!ext.isEmpty()) + ext = ext.prepend("."); + + QFileInfo fi(filename); + auto p = !path.isEmpty() ? path : fi.dir().path(); + base = QDir(p).filePath(fi.baseName() + ext); + if (!QFile::exists(base)) + return base; + + base.chop(ext.size()); + QString ret; + for (int suffix = 1;; suffix++) { + ret = QString("%1 (%2)%3").arg(base).arg(suffix).arg(ext); + if (!QFile::exists(ret)) { + return ret; + } + } +} + +void +DataTransferModel::registerTransferId(const QString& fileId, const QString& interactionId) +{ + pimpl_->file2InteractionId[fileId] = interactionId; + pimpl_->interactionToFileId.remove(interactionId); // Because a file transfer can be retried + pimpl_->interactionToFileId[interactionId] = fileId; +} + +DataTransferModel::DataTransferModel() + : QObject(nullptr) + , pimpl_ {std::make_unique<Impl>(*this)} +{} + +DataTransferModel::~DataTransferModel() = default; + +void +DataTransferModel::transferInfo(const QString& accountId, + const QString& fileId, + datatransfer::Info& lrc_info) +{ + DataTransferInfo infoFromDaemon; + if (ConfigurationManager::instance().dataTransferInfo(accountId, fileId, infoFromDaemon) == 0) { + lrc_info.uid = fileId; + lrc_info.status = convertDataTransferEvent( + DRing::DataTransferEventCode(infoFromDaemon.lastEvent)); + lrc_info.isOutgoing = !(infoFromDaemon.flags + & (1 << uint32_t(DRing::DataTransferFlags::direction))); + lrc_info.totalSize = infoFromDaemon.totalSize; + lrc_info.progress = infoFromDaemon.bytesProgress; + lrc_info.path = infoFromDaemon.path; + lrc_info.displayName = infoFromDaemon.displayName; + lrc_info.accountId = infoFromDaemon.accountId; + lrc_info.peerUri = infoFromDaemon.peer; + lrc_info.conversationId = infoFromDaemon.conversationId; + // lrc_info.timestamp = ? + return; + } + + lrc_info.status = datatransfer::Status::INVALID; +} + +void +DataTransferModel::sendFile(const QString& accountId, + const QString& peer_uri, + const QString& conversationId, + const QString& filePath, + const QString& displayName) +{ + if (conversationId.isEmpty()) { + // Fallback + DataTransferInfo info; +#ifdef ENABLE_LIBWRAP + DRing::DataTransferId id; +#else + qulonglong id; +#endif + info.accountId = accountId; + info.peer = peer_uri; + info.path = filePath; + info.conversationId = conversationId; + info.displayName = displayName; + info.bytesProgress = 0; + if (ConfigurationManager::instance().sendFileLegacy(info, id) != 0) + qWarning() << "DataTransferModel::sendFile(), error"; + return; + } + + ConfigurationManager::instance().sendFile(accountId, + conversationId, + filePath, + displayName, + {} /* TODO parent */); +} + +void +DataTransferModel::fileTransferInfo(const QString& accountId, + const QString& conversationId, + const QString& fileId, + QString& path, + qlonglong& total, + qlonglong& progress) +{ + ConfigurationManager::instance() + .fileTransferInfo(accountId, conversationId, fileId, path, total, progress); +} + +QString +DataTransferModel::accept(const QString& accountId, const QString& fileId, const QString& filePath) +{ + auto uniqueFilePath = pimpl_->getUniqueFilePath(filePath); + auto daemonFileId = pimpl_->interactionToFileId[fileId]; + ConfigurationManager::instance().acceptFileTransfer(accountId, daemonFileId, uniqueFilePath); + return uniqueFilePath; +} + +void +DataTransferModel::download(const QString& accountId, + const QString& convId, + const QString& interactionId, + const QString& fileId, + const QString& path) +{ + ConfigurationManager::instance().downloadFile(accountId, convId, interactionId, fileId, path); +} + +void +DataTransferModel::copyTo(const QString& accountId, + const QString& convId, + const QString& interactionId, + const QString& destPath, + const QString& displayName) +{ + auto fileId = getFileIdFromInteractionId(interactionId); + if (fileId.isEmpty()) { + qWarning() << "Cannot find any file for " << interactionId; + return; + } + QString path; + qlonglong total, progress; + + fileTransferInfo(accountId, convId, fileId, path, total, progress); + + auto src = QFile(path); + auto srcfi = QFileInfo(path); + if (!src.exists()) + return; + + auto filename = displayName; + if (displayName.isEmpty()) + filename = srcfi.isSymLink() ? srcfi.symLinkTarget() : path; + auto dest = pimpl_->getUniqueFilePath(filename, destPath); + qDebug() << "Copy to " << dest; + src.copy(dest); +} + +void +DataTransferModel::cancel(const QString& accountId, + const QString& conversationId, + const QString& interactionId) +{ + ConfigurationManager::instance().cancelDataTransfer(accountId, + conversationId, + getFileIdFromInteractionId(interactionId)); +} + +QString +DataTransferModel::getInteractionIdFromFileId(const QString& fileId) +{ + return pimpl_->file2InteractionId[fileId]; +} + +QString +DataTransferModel::getFileIdFromInteractionId(const QString& interactionId) +{ + return pimpl_->interactionToFileId[interactionId]; +} + +QString +DataTransferModel::createDefaultDirectory() +{ + auto defaultDirectory = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation) + + "/Jami"; + QDir dir(defaultDirectory); + if (!dir.exists()) + dir.mkpath("."); + return defaultDirectory; +} + +} // namespace api +} // namespace lrc + +#include "api/moc_datatransfermodel.cpp" +#include "datatransfermodel.moc" diff --git a/src/libclient/dbus/callmanager.cpp b/src/libclient/dbus/callmanager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..03097d1617a45259cd896bda7599b5c6731413aa --- /dev/null +++ b/src/libclient/dbus/callmanager.cpp @@ -0,0 +1,48 @@ +/**************************************************************************** + * Copyright (C) 2009-2022 Savoir-faire Linux Inc. * + * Author : Jérémy Quentin <jeremy.quentin@savoirfairelinux.com> * + * Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#include "callmanager.h" + +#include "../globalinstances.h" +#include "../interfaces/dbuserrorhandleri.h" + +CallManagerInterface& +CallManager::instance() +{ +#ifdef ENABLE_LIBWRAP + static auto interface = new CallManagerInterface(); +#else + if (!dbus_metaTypeInit) + registerCommTypes(); + + static auto interface = new CallManagerInterface("cx.ring.Ring", + "/cx/ring/Ring/CallManager", + QDBusConnection::sessionBus()); + + if (!interface->connection().isConnected()) { + GlobalInstances::dBusErrorHandler().connectionError( + "Error : jamid not connected. Service " + interface->service() + + " not connected. From call manager interface."); + } + if (!interface->isValid()) { + GlobalInstances::dBusErrorHandler().invalidInterfaceError( + "Error : jamid is not available, make sure it is running"); + } +#endif + return *interface; +} diff --git a/src/libclient/dbus/callmanager.h b/src/libclient/dbus/callmanager.h new file mode 100644 index 0000000000000000000000000000000000000000..f0201a51feb2ae5241ddb2d059b5074d12041fb0 --- /dev/null +++ b/src/libclient/dbus/callmanager.h @@ -0,0 +1,38 @@ +/**************************************************************************** + * Copyright (C) 2009-2022 Savoir-faire Linux Inc. * + * Author : Jérémy Quentin <jeremy.quentin@savoirfairelinux.com> * + * Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#ifdef ENABLE_TEST +#include "../../test/mocks/callmanager_mock.h" +#else +#ifdef ENABLE_LIBWRAP +#include "../qtwrapper/callmanager_wrap.h" +#else +#include "callmanager_dbus_interface.h" +#include <QDBusPendingReply> +#endif +#endif +#include <typedefs.h> + +namespace CallManager { + +/// Singleton to access dbus "CallManager" interface +LIB_EXPORT CallManagerInterface& instance(); + +} // namespace CallManager diff --git a/src/libclient/dbus/configurationmanager.cpp b/src/libclient/dbus/configurationmanager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..29b1a3974acc8afe74e6084bfa8ae22f8360f90c --- /dev/null +++ b/src/libclient/dbus/configurationmanager.cpp @@ -0,0 +1,46 @@ +/**************************************************************************** + * Copyright (C) 2009-2022 Savoir-faire Linux Inc. * + * Author : Jérémy Quentin <jeremy.quentin@savoirfairelinux.com> * + * Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#include "configurationmanager.h" + +#include "../globalinstances.h" +#include "../interfaces/dbuserrorhandleri.h" + +ConfigurationManagerInterface& +ConfigurationManager::instance() +{ +#ifdef ENABLE_LIBWRAP + static auto interface = new ConfigurationManagerInterface(); +#else + if (!dbus_metaTypeInit) + registerCommTypes(); + static auto interface = new ConfigurationManagerInterface("cx.ring.Ring", + "/cx/ring/Ring/ConfigurationManager", + QDBusConnection::sessionBus()); + if (!interface->connection().isConnected()) { + GlobalInstances::dBusErrorHandler().connectionError( + "Error : jamid not connected. Service " + interface->service() + + " not connected. From configuration manager interface."); + } + if (!interface->isValid()) { + GlobalInstances::dBusErrorHandler().invalidInterfaceError( + "Error : jamid is not available, make sure it is running"); + } +#endif + return *interface; +} diff --git a/src/libclient/dbus/configurationmanager.h b/src/libclient/dbus/configurationmanager.h new file mode 100644 index 0000000000000000000000000000000000000000..ce7e633bd8495fd692391ac1415728c0ef11608f --- /dev/null +++ b/src/libclient/dbus/configurationmanager.h @@ -0,0 +1,39 @@ +/**************************************************************************** + * Copyright (C) 2009-2022 Savoir-faire Linux Inc. * + * Author : Jérémy Quentin <jeremy.quentin@savoirfairelinux.com> * + * Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#ifdef ENABLE_TEST +#include "../../test/mocks/configurationmanager_mock.h" +#else +#ifdef ENABLE_LIBWRAP +#include "../qtwrapper/configurationmanager_wrap.h" +#else +#include "configurationmanager_dbus_interface.h" +#include <QDBusPendingReply> +#include "../qtwrapper/conversions_wrap.hpp" +#endif +#endif +#include <typedefs.h> + +namespace ConfigurationManager { + +/// Singleton to access the ConfigurationManager dbus interface +LIB_EXPORT ConfigurationManagerInterface& instance(); + +} // namespace ConfigurationManager diff --git a/src/libclient/dbus/instancemanager.cpp b/src/libclient/dbus/instancemanager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f245f67e27df4866e19bfd6aca8410e53684c46b --- /dev/null +++ b/src/libclient/dbus/instancemanager.cpp @@ -0,0 +1,67 @@ +/**************************************************************************** + * Copyright (C) 2009-2022 Savoir-faire Linux Inc. * + * Author : Jérémy Quentin <jeremy.quentin@savoirfairelinux.com> * + * Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include "instancemanager.h" + +#ifndef _MSC_VER +#include <unistd.h> +#else +#include "../../daemon/compat/msvc/unistd.h" +#endif // !_MSC_VER + +#include "../globalinstances.h" +#include "../interfaces/dbuserrorhandleri.h" + +InstanceManagerInterface& +InstanceManager::instance(bool muteDring) +{ +#ifdef ENABLE_LIBWRAP + static auto interface = new InstanceManagerInterface(muteDring); +#else + if (!dbus_metaTypeInit) + registerCommTypes(); + Q_UNUSED(muteDring) + + static auto interface = new InstanceManagerInterface("cx.ring.Ring", + "/cx/ring/Ring/Instance", + QDBusConnection::sessionBus()); + + if (!interface->connection().isConnected()) { + GlobalInstances::dBusErrorHandler().connectionError( + "Error : jamid not connected. Service " + interface->service() + + " not connected. From instance interface."); + } + static bool registered = false; + if (!registered) { + QDBusPendingReply<QString> reply = interface->Register(getpid(), ""); + registered = true; + reply.waitForFinished(); + } + + /* we do not check if the interface isValid; + * isValid() return 'false' if there was any error; + * we expect there to be an error when we first launch the client and the daemon is not yet + * running; + * TODO: check if we get the expected error, or another, see: + * http://doc.qt.io/qt-4.8/qdbuserror.html#ErrorType-enum + */ + +#endif + return *interface; +} diff --git a/src/libclient/dbus/instancemanager.h b/src/libclient/dbus/instancemanager.h new file mode 100644 index 0000000000000000000000000000000000000000..8759e2c9f72dd42a434f4a2fedd71468a890e5b5 --- /dev/null +++ b/src/libclient/dbus/instancemanager.h @@ -0,0 +1,37 @@ +/**************************************************************************** + * Copyright (C) 2009-2022 Savoir-faire Linux Inc. * + * Author : Jérémy Quentin <jeremy.quentin@savoirfairelinux.com> * + * Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#ifdef ENABLE_TEST +#include "../../test/mocks/instancemanager_mock.h" +#else +#ifdef ENABLE_LIBWRAP +#include "../qtwrapper/instancemanager_wrap.h" +#else +#include "instance_dbus_interface.h" +#include <QDBusPendingReply> +#endif +#endif +#include <typedefs.h> + +namespace InstanceManager { + +LIB_EXPORT InstanceManagerInterface& instance(bool muteDring = false); + +} diff --git a/src/libclient/dbus/metatypes.h b/src/libclient/dbus/metatypes.h new file mode 100644 index 0000000000000000000000000000000000000000..e84b91c93832d7bf5b3e6df9ac593a778bef7e8d --- /dev/null +++ b/src/libclient/dbus/metatypes.h @@ -0,0 +1,151 @@ +/****************************************************************************** + * Copyright (C) 2009-2022 Savoir-faire Linux Inc. * + * Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> * + * Jérémy Quentin <jeremy.quentin@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the Lesser GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +#pragma once + +#include <QtCore/QMetaType> +#include <QtCore/QMap> +#include <QtCore/QVector> +#include <QtCore/QString> + +#include "../typedefs.h" + +#ifndef ENABLE_LIBWRAP +#include <QtDBus/QtDBus> +#endif +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" + +Q_DECLARE_METATYPE(MapStringString) +Q_DECLARE_METATYPE(MapStringInt) +Q_DECLARE_METATYPE(VectorMapStringString) +Q_DECLARE_METATYPE(MapStringMapStringStringList) +Q_DECLARE_METATYPE(VectorInt) +Q_DECLARE_METATYPE(VectorUInt) +Q_DECLARE_METATYPE(VectorULongLong) +Q_DECLARE_METATYPE(VectorString) +Q_DECLARE_METATYPE(MapStringVectorString) +Q_DECLARE_METATYPE(VectorVectorByte) +Q_DECLARE_METATYPE(DataTransferInfo) +Q_DECLARE_METATYPE(uint64_t) +Q_DECLARE_METATYPE(Message) + +#ifndef ENABLE_LIBWRAP +static inline QDBusArgument& +operator<<(QDBusArgument& argument, const DataTransferInfo& info) +{ + argument.beginStructure(); + argument << info.accountId; + argument << info.lastEvent; + argument << info.flags; + argument << info.totalSize; + argument << info.bytesProgress; + argument << info.author; + argument << info.peer; + argument << info.conversationId; + argument << info.displayName; + argument << info.path; + argument << info.mimetype; + argument.endStructure(); + + return argument; +} + +static inline const QDBusArgument& +operator>>(const QDBusArgument& argument, DataTransferInfo& info) +{ + argument.beginStructure(); + argument >> info.accountId; + argument >> info.lastEvent; + argument >> info.flags; + argument >> info.totalSize; + argument >> info.bytesProgress; + argument >> info.author; + argument >> info.peer; + argument >> info.conversationId; + argument >> info.displayName; + argument >> info.path; + argument >> info.mimetype; + argument.endStructure(); + + return argument; +} + +static inline QDBusArgument& +operator<<(QDBusArgument& argument, const Message& m) +{ + argument.beginStructure(); + argument << m.from; + argument << m.payloads; + argument << m.received; + argument.endStructure(); + + return argument; +} + +static inline const QDBusArgument& +operator>>(const QDBusArgument& argument, Message& m) +{ + argument.beginStructure(); + argument >> m.from; + argument >> m.payloads; + argument >> m.received; + argument.endStructure(); + + return argument; +} +#endif + +#ifndef ENABLE_LIBWRAP +static bool dbus_metaTypeInit = false; +#endif +inline void +registerCommTypes() +{ +#ifndef ENABLE_LIBWRAP + qRegisterMetaType<MapStringString>("MapStringString"); + qDBusRegisterMetaType<MapStringString>(); + qRegisterMetaType<MapStringInt>("MapStringInt"); + qDBusRegisterMetaType<MapStringInt>(); + qRegisterMetaType<VectorMapStringString>("VectorMapStringString"); + qDBusRegisterMetaType<VectorMapStringString>(); + qRegisterMetaType<MapStringMapStringVectorString>("MapStringMapStringVectorString"); + qDBusRegisterMetaType<MapStringMapStringVectorString>(); + qRegisterMetaType<VectorInt>("VectorInt"); + qDBusRegisterMetaType<VectorInt>(); + qRegisterMetaType<VectorUInt>("VectorUInt"); + qDBusRegisterMetaType<VectorUInt>(); + qRegisterMetaType<VectorULongLong>("VectorULongLong"); + qDBusRegisterMetaType<VectorULongLong>(); + qRegisterMetaType<VectorString>("VectorString"); + qDBusRegisterMetaType<VectorString>(); + qRegisterMetaType<MapStringVectorString>("MapStringVectorString"); + qDBusRegisterMetaType<MapStringVectorString>(); + qRegisterMetaType<VectorVectorByte>("VectorVectorByte"); + qDBusRegisterMetaType<VectorVectorByte>(); + qRegisterMetaType<DataTransferInfo>("DataTransferInfo"); + qDBusRegisterMetaType<DataTransferInfo>(); + qRegisterMetaType<Message>("Message"); + qDBusRegisterMetaType<Message>(); + qRegisterMetaType<QVector<Message>>("QVector<Message>"); + qDBusRegisterMetaType<QVector<Message>>(); + dbus_metaTypeInit = true; +#endif +} + +#pragma GCC diagnostic pop diff --git a/src/libclient/dbus/pluginmanager.cpp b/src/libclient/dbus/pluginmanager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..246bac79f684decec6be69a273f4eae9709edad8 --- /dev/null +++ b/src/libclient/dbus/pluginmanager.cpp @@ -0,0 +1,46 @@ +/**************************************************************************** + * Copyright (C) 2013-2022 Savoir-faire Linux Inc. * + * Author : Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#include "pluginmanager.h" + +#include "../globalinstances.h" +#include "../interfaces/dbuserrorhandleri.h" + +PluginManagerInterface& +PluginManager::instance() +{ +#ifdef ENABLE_LIBWRAP + static auto interface = new PluginManagerInterface(); +#else + if (!dbus_metaTypeInit) + registerCommTypes(); + static auto interface = new PluginManagerInterface("cx.ring.Ring", + "/cx/ring/Ring/PluginManagerInterface", + QDBusConnection::sessionBus()); + + if (!interface->connection().isConnected()) { + GlobalInstances::dBusErrorHandler().connectionError( + "Error : jamid not connected. Service " + interface->service() + + " not connected. From presence interface."); + } + if (!interface->isValid()) { + GlobalInstances::dBusErrorHandler().invalidInterfaceError( + "Error : jamid is not available, make sure it is running"); + } +#endif + return *interface; +} diff --git a/src/libclient/dbus/pluginmanager.h b/src/libclient/dbus/pluginmanager.h new file mode 100644 index 0000000000000000000000000000000000000000..4c6274cdbd13cd22156b0971369564efd701950e --- /dev/null +++ b/src/libclient/dbus/pluginmanager.h @@ -0,0 +1,37 @@ +/**************************************************************************** + * Copyright (C) 2012-2022 Savoir-faire Linux Inc. * + * Author : Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#ifdef ENABLE_TEST +// #include "../../test/mocks/pluginmanager_mock.h" +#else +#ifdef ENABLE_LIBWRAP +#include "pluginmanager_wrap.h" +#else +#include "plugin_dbus_interface.h" +#include <QDBusPendingReply> +#endif +#endif + +#include <typedefs.h> + +namespace PluginManager { + +LIB_EXPORT PluginManagerInterface& instance(); + +} diff --git a/src/libclient/dbus/presencemanager.cpp b/src/libclient/dbus/presencemanager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7661c39c7ef7f8ec487d1f2ed56a84cf233729a8 --- /dev/null +++ b/src/libclient/dbus/presencemanager.cpp @@ -0,0 +1,46 @@ +/**************************************************************************** + * Copyright (C) 2013-2022 Savoir-faire Linux Inc. * + * Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#include "presencemanager.h" + +#include "../globalinstances.h" +#include "../interfaces/dbuserrorhandleri.h" + +PresenceManagerInterface& +PresenceManager::instance() +{ +#ifdef ENABLE_LIBWRAP + static auto interface = new PresenceManagerInterface(); +#else + if (!dbus_metaTypeInit) + registerCommTypes(); + static auto interface = new PresenceManagerInterface("cx.ring.Ring", + "/cx/ring/Ring/PresenceManager", + QDBusConnection::sessionBus()); + + if (!interface->connection().isConnected()) { + GlobalInstances::dBusErrorHandler().connectionError( + "Error : jamid not connected. Service " + interface->service() + + " not connected. From presence interface."); + } + if (!interface->isValid()) { + GlobalInstances::dBusErrorHandler().invalidInterfaceError( + "Error : jamid is not available, make sure it is running"); + } +#endif + return *interface; +} diff --git a/src/libclient/dbus/presencemanager.h b/src/libclient/dbus/presencemanager.h new file mode 100644 index 0000000000000000000000000000000000000000..a96a04237cbe2f6363c0f4c91231c205e1dc5409 --- /dev/null +++ b/src/libclient/dbus/presencemanager.h @@ -0,0 +1,36 @@ +/**************************************************************************** + * Copyright (C) 2012-2022 Savoir-faire Linux Inc. * + * Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once +#ifdef ENABLE_TEST +#include "../../test/mocks/presencemanager_mock.h" +#else +#ifdef ENABLE_LIBWRAP +#include "../qtwrapper/presencemanager_wrap.h" +#else +#include "presencemanager_dbus_interface.h" +#include <QDBusPendingReply> +#endif +#endif + +#include <typedefs.h> + +namespace PresenceManager { + +LIB_EXPORT PresenceManagerInterface& instance(); + +} diff --git a/src/libclient/dbus/videomanager.cpp b/src/libclient/dbus/videomanager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7b67573249b7a33dc979ecf82b6bb24ee8399409 --- /dev/null +++ b/src/libclient/dbus/videomanager.cpp @@ -0,0 +1,46 @@ +/**************************************************************************** + * Copyright (C) 2012-2022 Savoir-faire Linux Inc. * + * Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#include "videomanager.h" + +#include "../globalinstances.h" +#include "../interfaces/dbuserrorhandleri.h" + +VideoManagerInterface& +VideoManager::instance() +{ +#ifdef ENABLE_LIBWRAP + static auto interface = new VideoManagerInterface(); +#else + if (!dbus_metaTypeInit) + registerCommTypes(); + + static auto interface = new VideoManagerInterface("cx.ring.Ring", + "/cx/ring/Ring/VideoManager", + QDBusConnection::sessionBus()); + if (!interface->connection().isConnected()) { + GlobalInstances::dBusErrorHandler().connectionError( + "Error : jamid not connected. Service " + interface->service() + + " not connected. From video manager interface."); + } + if (!interface->isValid()) { + GlobalInstances::dBusErrorHandler().invalidInterfaceError( + "Error : jamid is not available, make sure it is running"); + } +#endif + return *interface; +} diff --git a/src/libclient/dbus/videomanager.h b/src/libclient/dbus/videomanager.h new file mode 100644 index 0000000000000000000000000000000000000000..a6c64f245fea7d63eff9fdef040c795f2c3daed5 --- /dev/null +++ b/src/libclient/dbus/videomanager.h @@ -0,0 +1,37 @@ +/**************************************************************************** + * Copyright (C) 2012-2022 Savoir-faire Linux Inc. * + * Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#ifdef ENABLE_TEST +#include "../../test/mocks/videomanager_mock.h" +#else +#ifdef ENABLE_LIBWRAP +#include "videomanager_wrap.h" +#else +#include "video_dbus_interface.h" +#include <QDBusPendingReply> +#endif +#endif + +#include <typedefs.h> + +namespace VideoManager { + +LIB_EXPORT VideoManagerInterface& instance(); + +} diff --git a/src/libclient/dbuserrorhandlerdefault.cpp b/src/libclient/dbuserrorhandlerdefault.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d92aa0ac1aaaf6170d37ac0e45630c7a9429be96 --- /dev/null +++ b/src/libclient/dbuserrorhandlerdefault.cpp @@ -0,0 +1,36 @@ +/**************************************************************************** + * Copyright (C) 2015-2022 Savoir-faire Linux Inc. * + * Author : Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>* + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#include "dbuserrorhandlerdefault.h" + +namespace Interfaces { + +void +DBusErrorHandlerDefault::connectionError(const QString& error) +{ + qDebug() << error; + throw error.toLatin1().constData(); +} + +void +DBusErrorHandlerDefault::invalidInterfaceError(const QString& error) +{ + qDebug() << error; + throw error.toLatin1().constData(); +} + +} // namespace Interfaces diff --git a/src/libclient/dbuserrorhandlerdefault.h b/src/libclient/dbuserrorhandlerdefault.h new file mode 100644 index 0000000000000000000000000000000000000000..540c99a6346e55399d4bdf63b09fed49d520dff6 --- /dev/null +++ b/src/libclient/dbuserrorhandlerdefault.h @@ -0,0 +1,36 @@ +/**************************************************************************** + * Copyright (C) 2015-2022 Savoir-faire Linux Inc. * + * Author : Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>* + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#include <typedefs.h> + +#include "interfaces/dbuserrorhandleri.h" + +namespace Interfaces { + +/** + * This implementation of the DBusErrorHandler interface throws an exception with the given message. + */ +class DBusErrorHandlerDefault : public DBusErrorHandlerI +{ +public: + [[noreturn]] void connectionError(const QString& error) override; + [[noreturn]] void invalidInterfaceError(const QString& error) override; +}; + +} // namespace Interfaces diff --git a/src/libclient/directrenderer.cpp b/src/libclient/directrenderer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f3d8383263c796c08280671ebe4eb8635a3f54a9 --- /dev/null +++ b/src/libclient/directrenderer.cpp @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2012-2022 Savoir-faire Linux Inc. + * Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com> + * Author: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com> + * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "directrenderer.h" + +#include "dbus/videomanager.h" +#include "videomanager_interface.h" + +#include <QMutex> + +namespace lrc { +namespace video { + +using namespace lrc::api::video; + +struct DirectRenderer::Impl : public QObject +{ + Q_OBJECT +public: + Impl(DirectRenderer* parent) + : QObject(nullptr) + , parent_(parent) + { + configureTarget(); + VideoManager::instance().registerSinkTarget(parent_->id(), target); + }; + ~Impl() + { + parent_->stopRendering(); + VideoManager::instance().registerSinkTarget(parent_->id(), {}); + } + + // sink target callbacks + void configureTarget() + { + using namespace std::placeholders; + target.pull = std::bind(&Impl::pullCallback, this); + target.push = std::bind(&Impl::pushCallback, this, _1); + }; + + DRing::FrameBuffer pullCallback() + { + QMutexLocker lk(&mutex); + if (!frameBufferPtr) { + frameBufferPtr.reset(av_frame_alloc()); + } + + // A response to this signal should be used to provide client + // allocated buffer specs via the AVFrame structure. + // Important: Subscription to this signal MUST be synchronous(Qt::DirectConnection). + Q_EMIT parent_->frameBufferRequested(frameBufferPtr.get()); + + if (frameBufferPtr->data[0] == nullptr) { + return nullptr; + } + + return std::move(frameBufferPtr); + }; + + void pushCallback(DRing::FrameBuffer buf) + { + { + QMutexLocker lk(&mutex); + frameBufferPtr = std::move(buf); + } + + Q_EMIT parent_->frameUpdated(); + }; + +private: + DirectRenderer* parent_; + +public: + DRing::SinkTarget target; + QMutex mutex; + DRing::FrameBuffer frameBufferPtr; +}; + +DirectRenderer::DirectRenderer(const QString& id, const QSize& res) + : Renderer(id, res) + , pimpl_(std::make_unique<DirectRenderer::Impl>(this)) +{} + +DirectRenderer::~DirectRenderer() {} + +void +DirectRenderer::startRendering() +{ + Q_EMIT started(); +} + +void +DirectRenderer::stopRendering() +{ + Q_EMIT stopped(); +} + +void +DirectRenderer::update(const QSize& res, const QString&) +{ + stopRendering(); + Renderer::update(res); + + VideoManager::instance().registerSinkTarget(id(), pimpl_->target); + startRendering(); +} + +Frame +DirectRenderer::currentFrame() const +{ + return {}; +} + +} // namespace video +} // namespace lrc + +#include "moc_directrenderer.cpp" +#include "directrenderer.moc" diff --git a/src/libclient/directrenderer.h b/src/libclient/directrenderer.h new file mode 100644 index 0000000000000000000000000000000000000000..dfcd026590123c9d23b717d4f7c27d5270ee4330 --- /dev/null +++ b/src/libclient/directrenderer.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2012-2022 Savoir-faire Linux Inc. + * Author : Alexandre Lision <alexandre.lision@savoirfairelinux.com> + * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "renderer.h" +#include "typedefs.h" + +namespace lrc { +namespace video { + +class DirectRenderer final : public Renderer +{ + Q_OBJECT +public: + DirectRenderer(const QString& id, const QSize& res); + ~DirectRenderer(); + + // Renderer interface. + void update(const QSize& res, const QString& shmPath) override; + lrc::api::video::Frame currentFrame() const override; + +public Q_SLOTS: + void startRendering() override; + void stopRendering() override; + +private: + struct Impl; + std::unique_ptr<Impl> pimpl_; +}; + +} // namespace video +} // namespace lrc diff --git a/src/libclient/globalinstances.cpp b/src/libclient/globalinstances.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a6ac6a19af2bd556b96ac2935e431736f69e6fa7 --- /dev/null +++ b/src/libclient/globalinstances.cpp @@ -0,0 +1,114 @@ +/**************************************************************************** + * Copyright (C) 2015-2022 Savoir-faire Linux Inc. * + * Author : Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>* + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#include "globalinstances.h" + +#include <memory> + +#include "interfaces/dbuserrorhandleri.h" +#include "interfaces/pixmapmanipulatori.h" + +#include "dbuserrorhandlerdefault.h" +#include "pixmapmanipulatordefault.h" + +namespace GlobalInstances { + +struct InstanceManager +{ + std::unique_ptr<Interfaces::DBusErrorHandlerI> m_dBusErrorHandler; + std::unique_ptr<Interfaces::PixmapManipulatorI> m_pixmapManipulator; +}; + +static InstanceManager& +instanceManager() +{ + static std::unique_ptr<InstanceManager> manager {new InstanceManager}; + return *manager.get(); +} +/** + * LRC does not provide a default implementation of this interface, thus an exception will be thrown + * if this getter is called without an instance being set by the client + */ + +Interfaces::DBusErrorHandlerI& +dBusErrorHandler() +{ + if (!instanceManager().m_dBusErrorHandler) + instanceManager().m_dBusErrorHandler.reset(new Interfaces::DBusErrorHandlerDefault); + return *instanceManager().m_dBusErrorHandler; +} + +void +setDBusErrorHandler(std::unique_ptr<Interfaces::DBusErrorHandlerI> instance) +{ + // do not allow empty pointers + if (!instance) { + qWarning() << "ignoring empty unique_ptr"; + return; + } + instanceManager().m_dBusErrorHandler = std::move(instance); +} + +/** + * LRC does not provide a default implementation of this interface, thus an exception will be thrown + * if this getter is called without an instance being set by the client + */ + +Interfaces::PixmapManipulatorI& +pixmapManipulator() +{ + if (!instanceManager().m_pixmapManipulator) + instanceManager().m_pixmapManipulator.reset(new Interfaces::PixmapManipulatorDefault); + return *instanceManager().m_pixmapManipulator.get(); +} + +void +setPixmapManipulator(std::unique_ptr<Interfaces::PixmapManipulatorI> instance) +{ + // do not allow empty pointers + if (!instance) { + qWarning() << "ignoring empty unique_ptr"; + return; + } + instanceManager().m_pixmapManipulator = std::move(instance); +} + +/* + * This API have some advantage over a more "explicit" one + * 1) It treat interfaces as class instead of as objects, making conceptual sense + * 2) It remove the boilerplate code related to creating the unique_ptr away from + * the client + * 3) It offer a transparent entry point for interface without having to + * extend the API when adding new interfaces + * 4) It mimic the addCollection interface, making the API more consistent. It + * also does so without the tick layer of black magic used in the Media and + * collection APIs. + */ +#define REGISTER_INTERFACE(I, m) \ + void setInterfaceInternal(I* i) { instanceManager().m = std::unique_ptr<I>(i); } + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmissing-declarations" + +REGISTER_INTERFACE(Interfaces::DBusErrorHandlerI, m_dBusErrorHandler) +REGISTER_INTERFACE(Interfaces::PixmapManipulatorI, m_pixmapManipulator) + +#pragma GCC diagnostic pop + +#undef REGISTER_INTERFACE + +} // namespace GlobalInstances diff --git a/src/libclient/globalinstances.h b/src/libclient/globalinstances.h new file mode 100644 index 0000000000000000000000000000000000000000..d81546520bfc992605601496803bc429dcef37b3 --- /dev/null +++ b/src/libclient/globalinstances.h @@ -0,0 +1,87 @@ +/**************************************************************************** + * Copyright (C) 2015-2022 Savoir-faire Linux Inc. * + * Author : Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>* + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#include <typedefs.h> + +#include <memory> + +namespace Interfaces { +class ContactMethodSelectorI; +class DBusErrorHandlerI; +class PixmapManipulatorI; +class ShortcutCreatorI; +} // namespace Interfaces + +/** + * Use these functions to get and set the global instance of the implementation of each interface. + * + * The setter functions demand an std::unique_ptr because they become the object owners. + * + * Note that certain interfaces do not have a default implementation in LRC, in this case the getter + * function will throw an exception if no instance has been set by the client. + */ +namespace GlobalInstances { + +/** + * LRC does not provide a default implementation of this interface, thus an exception will be thrown + * if this getter is called without an instance being set by the client + */ + +Interfaces::DBusErrorHandlerI& dBusErrorHandler(); +void setDBusErrorHandler(std::unique_ptr<Interfaces::DBusErrorHandlerI> instance); + +/** + * LRC does not provide a default implementation of this interface, thus an exception will be thrown + * if this getter is called without an instance being set by the client + */ + +LIB_EXPORT Interfaces::PixmapManipulatorI& pixmapManipulator(); +void LIB_EXPORT setPixmapManipulator(std::unique_ptr<Interfaces::PixmapManipulatorI> instance); + +LIB_EXPORT Interfaces::ShortcutCreatorI& shortcutCreator(); +void LIB_EXPORT setShortcutCreator(std::unique_ptr<Interfaces::ShortcutCreatorI> instance); + +// Private use only +void setInterfaceInternal(Interfaces::ContactMethodSelectorI*); +void setInterfaceInternal(Interfaces::DBusErrorHandlerI*); +void setInterfaceInternal(Interfaces::PixmapManipulatorI*); +void setInterfaceInternal(Interfaces::ShortcutCreatorI*); + +/** + * Generic interface setter. This metamethod can set any type of interface + * dynamically using variadic template, compile time type deduction and + * the macro subsystem. Passing an invalid interface should trigger compile + * time errors. + * + * The interface object is created internally and additional parameters + * can be passed. + */ +template<class I, typename... Ts> +void +setInterface(Ts... args) +{ + try { + auto i = new I(args...); + setInterfaceInternal(i); + } catch (void* e) { // TODO define some kind of object for errors like this + qDebug() << "Interface could not be set"; + } +} + +} // namespace GlobalInstances diff --git a/src/libclient/interfaces/dbuserrorhandleri.h b/src/libclient/interfaces/dbuserrorhandleri.h new file mode 100644 index 0000000000000000000000000000000000000000..0ac27ccc530e1ae94e70551eaf701fa008fbff7c --- /dev/null +++ b/src/libclient/interfaces/dbuserrorhandleri.h @@ -0,0 +1,38 @@ +/**************************************************************************** + * Copyright (C) 2015-2022 Savoir-faire Linux Inc. * + * Author : Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>* + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#include <typedefs.h> + +namespace Interfaces { + +/** + * Some clients may not have a nice way to generally handle exceptions event wide (ie: handle any + * exception which may occur during an itteration or an event on the main loop). This interface + * gives them the option to implement various ways to handle dbus errors. + */ +class DBusErrorHandlerI +{ +public: + virtual ~DBusErrorHandlerI() = default; + + virtual void connectionError(const QString& error) = 0; + virtual void invalidInterfaceError(const QString& error) = 0; +}; + +} // namespace Interfaces diff --git a/src/libclient/interfaces/pixmapmanipulatori.h b/src/libclient/interfaces/pixmapmanipulatori.h new file mode 100644 index 0000000000000000000000000000000000000000..1f8e5fe02bd2a4db8db57c62d6b8862c2992927f --- /dev/null +++ b/src/libclient/interfaces/pixmapmanipulatori.h @@ -0,0 +1,105 @@ +/**************************************************************************** + * Copyright (C) 2013-2022 Savoir-faire Linux Inc. * + * Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#include <typedefs.h> + +// Qt +class QVariant; +class QModelIndex; +class QByteArray; + +// Ring +struct UserActionElement; + +namespace lrc { +namespace api { +namespace account { +struct Info; +} +namespace conversation { +struct Info; +} +} // namespace api +} // namespace lrc + +namespace Interfaces { + +/** + * Different clients can have multiple way of displaying images. Some may + * add borders, other add corner radius (see Ubuntu-SDK HIG). This + * abstract class define many operations that can be defined by each clients. + * + * Most methods return QVariants as this library doesn't link against QtGui + * + * This interface is not frozen, more methods may be added later. + */ +class PixmapManipulatorI +{ +public: + // Implementation can use random values to extend this + enum CollectionIconHint { + NONE, + HISTORY, + CONTACT, + BOOKMARK, + PHONE_NUMBER, + RINGTONE, + PROFILE, + CERTIFICATE, + ACCOUNT, + RECORDING, + MACRO, + }; + + virtual ~PixmapManipulatorI() = default; + + virtual QVariant conversationPhoto(const lrc::api::conversation::Info& conversation, + const lrc::api::account::Info& accountInfo, + const QSize& size, + bool displayPresence = true) + { + Q_UNUSED(conversation); + Q_UNUSED(accountInfo); + Q_UNUSED(size); + Q_UNUSED(displayPresence); + return {}; + } + virtual QVariant numberCategoryIcon(const QVariant& p, + const QSize& size, + bool displayPresence = false, + bool isPresent = false) + = 0; + virtual QByteArray toByteArray(const QVariant& pxm) = 0; + virtual QVariant personPhoto(const QByteArray& data, const QString& type = "PNG") = 0; + virtual QVariant decorationRole(const QModelIndex& index) = 0; + virtual QVariant decorationRole(const lrc::api::conversation::Info& conversation, + const lrc::api::account::Info& accountInfo) + { + Q_UNUSED(conversation); + Q_UNUSED(accountInfo); + return {}; + } + + /** + * Return the icons associated with the action and its state + */ + virtual QVariant userActionIcon(const UserActionElement& state) const = 0; +}; + +} // namespace Interfaces diff --git a/src/libclient/lrc.cpp b/src/libclient/lrc.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7d4c80e4f6f851f60cf48c6c00ced02a68a01eda --- /dev/null +++ b/src/libclient/lrc.cpp @@ -0,0 +1,248 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author : Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * + * Author : Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * Author : Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#include "api/lrc.h" + +#include <locale> + +#ifndef _MSC_VER +#include <unistd.h> +#else +#include "../../daemon/compat/msvc/unistd.h" +#endif // !_MSC_VER + +#include "call_const.h" + +// Models and database +#include "api/avmodel.h" +#include "api/pluginmodel.h" +#include "api/behaviorcontroller.h" +#include "api/datatransfermodel.h" +#include "api/newaccountmodel.h" +#include "callbackshandler.h" +#include "dbus/callmanager.h" +#include "dbus/configurationmanager.h" +#include "dbus/instancemanager.h" +#include "dbus/configurationmanager.h" +#include "authority/storagehelper.h" + +namespace lrc { + +using namespace api; + +std::atomic_bool lrc::api::Lrc::holdConferences; +std::atomic_bool lrc::api::Lrc::cacheAvatars {true}; + +// To judge whether the call is finished or not depending on callState +bool isFinished(const QString& callState); + +class LrcPimpl +{ +public: + LrcPimpl(Lrc& linked, MigrationCb& willMigrateCb, MigrationCb& didMigrateCb); + + const Lrc& linked; + std::unique_ptr<BehaviorController> behaviorController; + std::unique_ptr<CallbacksHandler> callbackHandler; + std::unique_ptr<NewAccountModel> accountModel; + std::unique_ptr<AVModel> AVModel_; + std::unique_ptr<PluginModel> PluginModel_; +}; + +Lrc::Lrc(MigrationCb willDoMigrationCb, MigrationCb didDoMigrationCb, bool muteDring) +{ + lrc::api::Lrc::holdConferences.store(true); +#ifndef ENABLE_LIBWRAP + // Replace locale for timestamps + std::locale::global(std::locale("")); +#else +#ifdef Q_OS_LINUX + if (!getenv("JAMI_DISABLE_SHM")) + setenv("JAMI_DISABLE_SHM", "1", true); +#endif +#endif + // Ensure Daemon is running/loaded (especially on non-DBus platforms) + // before instantiating LRC and its members + InstanceManager::instance(muteDring); + lrcPimpl_ = std::make_unique<LrcPimpl>(*this, willDoMigrationCb, didDoMigrationCb); +} + +Lrc::~Lrc() +{ + // Unregister from the daemon + InstanceManagerInterface& instance = InstanceManager::instance(); + Q_NOREPLY instance.Unregister(getpid()); +#ifndef ENABLE_LIBWRAP + instance.connection().disconnectFromBus(instance.connection().baseService()); +#endif // ENABLE_LIBWRAP +} + +NewAccountModel& +Lrc::getAccountModel() const +{ + return *lrcPimpl_->accountModel; +} + +BehaviorController& +Lrc::getBehaviorController() const +{ + return *lrcPimpl_->behaviorController; +} + +AVModel& +Lrc::getAVModel() const +{ + return *lrcPimpl_->AVModel_; +} + +PluginModel& +Lrc::getPluginModel() const +{ + return *lrcPimpl_->PluginModel_; +} + +void +Lrc::connectivityChanged() const +{ + ConfigurationManager::instance().connectivityChanged(); +} + +bool +Lrc::isConnected() +{ +#ifdef ENABLE_LIBWRAP + return true; +#else + return ConfigurationManager::instance().connection().isConnected(); +#endif +} + +bool +Lrc::dbusIsValid() +{ +#ifdef ENABLE_LIBWRAP + return true; +#else + return ConfigurationManager::instance().isValid(); +#endif +} + +void +Lrc::subscribeToDebugReceived() +{ + lrcPimpl_->callbackHandler->subscribeToDebugReceived(); +} + +VectorString +Lrc::activeCalls() +{ + VectorString result; + const QStringList accountIds = ConfigurationManager::instance().getAccountList(); + for (const auto& accId : accountIds) { + QStringList callLists = CallManager::instance().getCallList(accId); + for (const auto& call : callLists) { + MapStringString callDetails = CallManager::instance().getCallDetails(accId, call); + if (!isFinished(callDetails[QString(DRing::Call::Details::CALL_STATE)])) + result.push_back(call); + } + } + return result; +} + +void +Lrc::hangupCallsAndConferences() +{ + const QStringList accountIds = ConfigurationManager::instance().getAccountList(); + for (const auto& accId : accountIds) { + QStringList conferences = CallManager::instance().getConferenceList(accId); + for (const auto& conf : conferences) { + CallManager::instance().hangUpConference(accId, conf); + } + QStringList calls = CallManager::instance().getCallList(accId); + for (const auto& call : calls) { + CallManager::instance().hangUp(accId, call); + } + } +} + +VectorString +Lrc::getCalls() +{ + QStringList callLists = CallManager::instance().getCallList(""); + VectorString result; + result.reserve(callLists.size()); + for (const auto& call : callLists) { + result.push_back(call); + } + return result; +} + +VectorString +Lrc::getConferences(const QString& accountId) +{ + VectorString result; + if (accountId.isEmpty()) { + const QStringList accountIds = ConfigurationManager::instance().getAccountList(); + for (const auto& accId : accountIds) { + QStringList conferencesList = CallManager::instance().getConferenceList(accId); + for (const auto& conf : conferencesList) + result.push_back(conf); + } + } else { + QStringList conferencesList = CallManager::instance().getConferenceList(accountId); + for (const auto& conf : conferencesList) + result.push_back(conf); + } + return result; +} + +bool +isFinished(const QString& callState) +{ + if (callState == QLatin1String(DRing::Call::StateEvent::HUNGUP) + || callState == QLatin1String(DRing::Call::StateEvent::BUSY) + || callState == QLatin1String(DRing::Call::StateEvent::PEER_BUSY) + || callState == QLatin1String(DRing::Call::StateEvent::FAILURE) + || callState == QLatin1String(DRing::Call::StateEvent::INACTIVE) + || callState == QLatin1String(DRing::Call::StateEvent::OVER)) { + return true; + } + return false; +} + +void +Lrc::monitor(bool continuous) +{ + ConfigurationManager::instance().monitor(continuous); +} + +LrcPimpl::LrcPimpl(Lrc& linked, MigrationCb& willMigrateCb, MigrationCb& didMigrateCb) + : linked(linked) + , behaviorController(std::make_unique<BehaviorController>()) + , callbackHandler(std::make_unique<CallbacksHandler>(linked)) + , accountModel(std::make_unique<NewAccountModel>(linked, + *callbackHandler, + *behaviorController, + willMigrateCb, + didMigrateCb)) + , AVModel_ {std::make_unique<AVModel>(*callbackHandler)} + , PluginModel_ {std::make_unique<PluginModel>()} +{} + +} // namespace lrc diff --git a/src/libclient/messagelistmodel.cpp b/src/libclient/messagelistmodel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8bd33ebeaf12ba971001febe0243b77c3ea613c5 --- /dev/null +++ b/src/libclient/messagelistmodel.cpp @@ -0,0 +1,480 @@ +/* + * Copyright (C) 2020-2022 Savoir-faire Linux Inc. + * + * Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com> + * Author: Trevor Tabah <trevor.tabah@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "messagelistmodel.h" + +#include "api/conversationmodel.h" +#include "api/interaction.h" + +#include <QAbstractListModel> + +namespace lrc { + +using namespace api; + +using constIterator = MessageListModel::constIterator; +using iterator = MessageListModel::iterator; +using reverseIterator = MessageListModel::reverseIterator; + +MessageListModel::MessageListModel(QObject* parent) + : QAbstractListModel(parent) +{} + +QPair<iterator, bool> +MessageListModel::emplace(const QString& msgId, interaction::Info message, bool beginning) +{ + iterator it; + for (it = interactions_.begin(); it != interactions_.end(); ++it) { + if (it->first == msgId) { + return qMakePair(it, false); + } + } + auto iter = beginning ? interactions_.begin() : interactions_.end(); + auto iterator = insertMessage(iter, qMakePair(msgId, message)); + return qMakePair(iterator, true); +} + +iterator +MessageListModel::find(const QString& msgId) +{ + iterator it; + for (it = interactions_.begin(); it != interactions_.end(); ++it) { + if (it->first == msgId) { + return it; + } + } + return interactions_.end(); +} + +constIterator +MessageListModel::find(const QString& msgId) const +{ + constIterator it; + for (it = interactions_.cbegin(); it != interactions_.cend(); ++it) { + if (it->first == msgId) { + return it; + } + } + return interactions_.cend(); +} + +QPair<iterator, bool> +MessageListModel::insert(std::pair<QString, interaction::Info> message, bool beginning) +{ + return emplace(message.first, message.second, beginning); +} + +int +MessageListModel::erase(const QString& msgId) +{ + iterator it; + int index = 0; + for (it = interactions_.begin(); it != interactions_.end(); ++it) { + if (it->first == msgId) { + removeMessage(index, it); + return 1; + } + index++; + } + return 0; +} + +interaction::Info& +MessageListModel::operator[](const QString& messageId) +{ + for (auto it = interactions_.cbegin(); it != interactions_.cend(); ++it) { + if (it->first == messageId) { + return const_cast<interaction::Info&>(it->second); + } + } + // element not find, add it to the end + interaction::Info newMessage = {}; + insertMessage(interactions_.end(), qMakePair(messageId, newMessage)); + if (interactions_.last().first == messageId) { + return const_cast<interaction::Info&>(interactions_.last().second); + } + throw std::out_of_range("Cannot find message"); +} + +iterator +MessageListModel::end() +{ + return interactions_.end(); +} + +constIterator +MessageListModel::end() const +{ + return interactions_.end(); +} + +constIterator +MessageListModel::cend() const +{ + return interactions_.cend(); +} + +iterator +MessageListModel::begin() +{ + return interactions_.begin(); +} + +constIterator +MessageListModel::begin() const +{ + return interactions_.begin(); +} + +reverseIterator +MessageListModel::rbegin() +{ + return interactions_.rbegin(); +} + +int +MessageListModel::size() const +{ + return interactions_.size(); +} + +void +MessageListModel::clear(int leaveN) +{ + interactions_.erase(interactions_.begin(), std::prev(interactions_.end(), leaveN)); +} + +bool +MessageListModel::empty() const +{ + return interactions_.empty(); +} + +interaction::Info +MessageListModel::at(const QString& msgId) const +{ + for (auto it = interactions_.cbegin(); it != interactions_.cend(); ++it) { + if (it->first == msgId) { + return it->second; + } + } + return {}; +} + +QPair<QString, interaction::Info> +MessageListModel::front() const +{ + return interactions_.front(); +} + +QPair<QString, interaction::Info> +MessageListModel::last() const +{ + return interactions_.last(); +} + +QPair<QString, interaction::Info> +MessageListModel::atIndex(int index) const +{ + return interactions_.at(index); +} + +QPair<iterator, bool> +MessageListModel::insert(int index, QPair<QString, interaction::Info> message) +{ + iterator itr; + for (itr = interactions_.begin(); itr != interactions_.end(); ++itr) { + if (itr->first == message.first) { + return qMakePair(itr, false); + } + } + if (index >= size()) { + auto iterator = insertMessage(interactions_.end(), message); + return qMakePair(iterator, true); + } + insertMessage(index, message); + return qMakePair(interactions_.end(), true); +} + +int +MessageListModel::indexOfMessage(const QString& msgId, bool reverse) const +{ + auto getIndex = [reverse, &msgId](const auto& start, const auto& end) -> int { + auto it = std::find_if(start, end, [&msgId](const auto& it) { return it.first == msgId; }); + if (it == end) { + return -1; + } + return reverse ? std::distance(it, end) - 1 : std::distance(start, it); + }; + return reverse ? getIndex(interactions_.rbegin(), interactions_.rend()) + : getIndex(interactions_.begin(), interactions_.end()); +} + +void +MessageListModel::moveMessages(QList<QString> msgIds, const QString& parentId) +{ + for (auto msgId : msgIds) { + moveMessage(msgId, parentId); + } +} + +void +MessageListModel::moveMessage(const QString& msgId, const QString& parentId) +{ + int currentIndex = indexOfMessage(msgId); + if (currentIndex == -1) { + qWarning() << "Incorrect index detected in MessageListModel::moveMessage"; + return; + } + + // if we have a next element check if it is a child interaction + QString childMessageIdToMove; + if (currentIndex < (interactions_.size() - 1)) { + const auto& next = interactions_.at(currentIndex + 1); + if (next.second.parentId == msgId) { + childMessageIdToMove = next.first; + } + } + + // move a message + int newIndex = indexOfMessage(parentId) + 1; + if (newIndex >= interactions_.size()) { + newIndex = interactions_.size() - 1; + } + + if (currentIndex == newIndex || newIndex == -1) + return; + + moveMessage(currentIndex, newIndex); + + // move a child message + if (!childMessageIdToMove.isEmpty()) { + moveMessage(childMessageIdToMove, msgId); + } +} + +void +MessageListModel::insertMessage(int index, item_t& message) +{ + Q_EMIT beginInsertRows(QModelIndex(), index, index); + interactions_.insert(index, message); + Q_EMIT endInsertRows(); +} + +iterator +MessageListModel::insertMessage(iterator it, item_t& message) +{ + auto index = std::distance(begin(), it); + Q_EMIT beginInsertRows(QModelIndex(), index, index); + auto insertion = interactions_.insert(it, message); + Q_EMIT endInsertRows(); + return insertion; +} + +void +MessageListModel::removeMessage(int index, iterator it) +{ + Q_EMIT beginRemoveRows(QModelIndex(), index, index); + interactions_.erase(it); + Q_EMIT endRemoveRows(); +} + +void +MessageListModel::moveMessage(int from, int to) +{ + Q_EMIT beginMoveRows(QModelIndex(), from, from, QModelIndex(), to); + interactions_.move(from, to); + Q_EMIT endMoveRows(); +} + +bool +MessageListModel::contains(const QString& msgId) +{ + return find(msgId) != interactions_.end(); +} + +int +MessageListModel::rowCount(const QModelIndex&) const +{ + return interactions_.size(); +} + +QHash<int, QByteArray> +MessageListModel::roleNames() const +{ + using namespace MessageList; + QHash<int, QByteArray> roles; +#define X(role) roles[role] = #role; + MSG_ROLES +#undef X + return roles; +} + +QVariant +MessageListModel::dataForItem(item_t item, int, int role) const +{ + switch (role) { + case Role::Id: + return QVariant(item.first); + case Role::Author: + return QVariant(item.second.authorUri); + case Role::Body: + return QVariant(item.second.body); + case Role::Timestamp: + return QVariant::fromValue(item.second.timestamp); + case Role::Duration: + return QVariant::fromValue(item.second.duration); + case Role::Type: + return QVariant(static_cast<int>(item.second.type)); + case Role::Status: + return QVariant(static_cast<int>(item.second.status)); + case Role::IsRead: + return QVariant(item.second.isRead); + case Role::LinkPreviewInfo: + return QVariant(item.second.linkPreviewInfo); + case Role::Linkified: + return QVariant(item.second.linkified); + case Role::ActionUri: + return QVariant(item.second.commit["uri"]); + case Role::ContactAction: + return QVariant(item.second.commit["action"]); + case Role::TransferName: + return QVariant(item.second.commit["displayName"]); + case Role::Readers: + return QVariant(messageToReaders_[item.first]); + default: + return {}; + } +} + +QVariant +MessageListModel::data(const QModelIndex& index, int role) const +{ + if (!index.isValid() || index.row() < 0 || index.row() >= rowCount()) { + return {}; + } + return dataForItem(interactions_.at(index.row()), index.row(), role); +} + +int +MessageListModel::getIndexOfMessage(const QString& messageId) const +{ + for (int i = 0; i < interactions_.size(); i++) { + if (atIndex(i).first == messageId) { + return i; + } + } + return -1; +} + +void +MessageListModel::addHyperlinkInfo(const QString& messageId, const QVariantMap& info) +{ + int index = getIndexOfMessage(messageId); + if (index == -1) { + return; + } + QModelIndex modelIndex = QAbstractListModel::index(index, 0); + + interactions_[index].second.linkPreviewInfo = info; + Q_EMIT dataChanged(modelIndex, modelIndex, {Role::LinkPreviewInfo}); +} + +void +MessageListModel::linkifyMessage(const QString& messageId, const QString& linkified) +{ + int index = getIndexOfMessage(messageId); + if (index == -1) { + return; + } + QModelIndex modelIndex = QAbstractListModel::index(index, 0); + interactions_[index].second.body = linkified; + interactions_[index].second.linkified = true; + Q_EMIT dataChanged(modelIndex, modelIndex, {Role::Body, Role::Linkified}); +} + +void +MessageListModel::setRead(const QString& peer, const QString& messageId) +{ + auto i = lastDisplayedMessageUid_.find(peer); + if (i != lastDisplayedMessageUid_.end()) { + auto old = i.value(); + messageToReaders_[old].removeAll(peer); + auto msgIdx = getIndexOfMessage(old); + // Remove from latest read + if (msgIdx != -1) { + QModelIndex modelIndex = QAbstractListModel::index(msgIdx, 0); + Q_EMIT dataChanged(modelIndex, modelIndex, {Role::Readers}); + } + } + // update map + lastDisplayedMessageUid_[peer] = messageId; + messageToReaders_[messageId].append(peer); + // update interaction + auto msgIdx = getIndexOfMessage(messageId); + // Remove from latest read + if (msgIdx != -1) { + QModelIndex modelIndex = QAbstractListModel::index(msgIdx, 0); + Q_EMIT dataChanged(modelIndex, modelIndex, {Role::Readers}); + } +} + +QString +MessageListModel::getRead(const QString& peer) +{ + auto i = lastDisplayedMessageUid_.find(peer); + if (i != lastDisplayedMessageUid_.end()) + return i.value(); + return ""; +} + +void +MessageListModel::emitBeginResetModel() +{ + Q_EMIT beginResetModel(); +} + +void +MessageListModel::emitEndResetModel() +{ + Q_EMIT endResetModel(); +} + +void +MessageListModel::emitDataChanged(iterator it, VectorInt roles) +{ + auto index = std::distance(begin(), it); + QModelIndex modelIndex = QAbstractListModel::index(index, 0); + Q_EMIT dataChanged(modelIndex, modelIndex, roles); +} + +void +MessageListModel::emitDataChanged(const QString& msgId, VectorInt roles) +{ + int index = getIndexOfMessage(msgId); + if (index == -1) { + return; + } + QModelIndex modelIndex = QAbstractListModel::index(index, 0); + Q_EMIT dataChanged(modelIndex, modelIndex, roles); +} + +} // namespace lrc diff --git a/src/libclient/messagelistmodel.h b/src/libclient/messagelistmodel.h new file mode 100644 index 0000000000000000000000000000000000000000..f369a3b6dc703b8885fcca012c79f8fb2f3b33d8 --- /dev/null +++ b/src/libclient/messagelistmodel.h @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2020-2022 Savoir-faire Linux Inc. + * + * Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com> + * Author: Trevor Tabah <trevor.tabah@savoirfairelinux.com> + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#pragma once + +#include "api/interaction.h" + +#include <QAbstractListModel> + +namespace lrc { +namespace api { + +namespace interaction { +struct Info; +} + +#define MSG_ROLES \ + X(Id) \ + X(Author) \ + X(Body) \ + X(ParentId) \ + X(Timestamp) \ + X(Duration) \ + X(Type) \ + X(Status) \ + X(IsRead) \ + X(ContactAction) \ + X(ActionUri) \ + X(LinkPreviewInfo) \ + X(Linkified) \ + X(TransferName) \ + X(Readers) + +namespace MessageList { +Q_NAMESPACE +enum Role { + DummyRole = Qt::UserRole + 1, +#define X(role) role, + MSG_ROLES +#undef X +}; +Q_ENUM_NS(Role) +} // namespace MessageList + +class MessageListModel : public QAbstractListModel +{ + Q_OBJECT + +public: + using item_t = const QPair<QString, interaction::Info>; + + typedef QList<QPair<QString, interaction::Info>>::ConstIterator constIterator; + typedef QList<QPair<QString, interaction::Info>>::Iterator iterator; + typedef QList<QPair<QString, interaction::Info>>::reverse_iterator reverseIterator; + + explicit MessageListModel(QObject* parent = nullptr); + ~MessageListModel() = default; + + // map functions + QPair<iterator, bool> emplace(const QString& msgId, + interaction::Info message, + bool beginning = false); + iterator find(const QString& msgId); + constIterator find(const QString& msgId) const; + QPair<iterator, bool> insert(std::pair<QString, interaction::Info> message, + bool beginning = false); + Q_INVOKABLE int erase(const QString& msgId); + interaction::Info& operator[](const QString& messageId); + iterator end(); + constIterator end() const; + constIterator cend() const; + iterator begin(); + constIterator begin() const; + reverseIterator rbegin(); + int size() const; + void clear(int leaveN = 0); + bool empty() const; + interaction::Info at(const QString& intId) const; + QPair<QString, interaction::Info> front() const; + QPair<QString, interaction::Info> last() const; + QPair<QString, interaction::Info> atIndex(int index) const; + + QPair<iterator, bool> insert(int index, QPair<QString, interaction::Info> message); + int indexOfMessage(const QString& msgId, bool reverse = true) const; + void moveMessages(QList<QString> msgIds, const QString& parentId); + + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; + QHash<int, QByteArray> roleNames() const override; + QVariant dataForItem(item_t item, int indexRow, int role = Qt::DisplayRole) const; + bool contains(const QString& msgId); + int getIndexOfMessage(const QString& messageId) const; + void addHyperlinkInfo(const QString& messageId, const QVariantMap& info); + void linkifyMessage(const QString& messageId, const QString& linkified); + + void setRead(const QString& peer, const QString& messageId); + QString getRead(const QString& peer); + + // use these if the underlying data model is changed from conversationmodel + // Note: this is not ideal, and this class should be refactored into a proper + // view model and absorb the interaction management logic to avoid exposing + // these emission wrappers + void emitBeginResetModel(); + void emitEndResetModel(); + void emitDataChanged(iterator it, VectorInt roles = {}); + void emitDataChanged(const QString& msgId, VectorInt roles = {}); + +protected: + using Role = MessageList::Role; + +private: + QList<QPair<QString, interaction::Info>> interactions_; + // Note: because read status are updated even if interaction is not loaded + // we need to keep track of these status outside the interaction::Info + // lastDisplayedMessageUid_ stores: {"peerId":"messageId"} + // messageToReaders_ caches: "messageId":["peer1", "peer2"] + // to allow quick access. + QMap<QString, QString> lastDisplayedMessageUid_; + QMap<QString, QStringList> messageToReaders_; + + void moveMessage(const QString& msgId, const QString& parentId); + void insertMessage(int index, item_t& message); + iterator insertMessage(iterator it, item_t& message); + void removeMessage(int index, iterator it); + void moveMessage(int from, int to); +}; +} // namespace api +} // namespace lrc +Q_DECLARE_METATYPE(lrc::api::MessageListModel*) diff --git a/src/libclient/namedirectory.cpp b/src/libclient/namedirectory.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8091900875c61110087649856ee39968bd933f23 --- /dev/null +++ b/src/libclient/namedirectory.cpp @@ -0,0 +1,123 @@ +/**************************************************************************** + * Copyright (C) 2016-2022 Savoir-faire Linux Inc. * + * Author : Alexandre Viau <alexandre.viau@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include <QCoreApplication> + +#include "namedirectory.h" +#include "private/namedirectory_p.h" +#include "dbus/configurationmanager.h" + +NameDirectoryPrivate::NameDirectoryPrivate(NameDirectory* q) + : q_ptr(q) +{ + ConfigurationManagerInterface& configurationManager = ConfigurationManager::instance(); + + connect(&configurationManager, + &ConfigurationManagerInterface::nameRegistrationEnded, + this, + &NameDirectoryPrivate::slotNameRegistrationEnded, + Qt::QueuedConnection); + connect(&configurationManager, + &ConfigurationManagerInterface::registeredNameFound, + this, + &NameDirectoryPrivate::slotRegisteredNameFound, + Qt::QueuedConnection); + connect(&configurationManager, + &ConfigurationManagerInterface::exportOnRingEnded, + this, + &NameDirectoryPrivate::slotExportOnRingEnded, + Qt::QueuedConnection); +} + +NameDirectory::NameDirectory() + : QObject(QCoreApplication::instance()) + , d_ptr(new NameDirectoryPrivate(this)) +{} + +/// Singleton +NameDirectory& +NameDirectory::instance() +{ + static auto instance = new NameDirectory; + return *instance; +} + +// Name registration ended +void +NameDirectoryPrivate::slotNameRegistrationEnded(const QString& accountId, + int status, + const QString& name) +{ + qDebug() << "Name registration ended. Account:" << accountId << "status:" << status + << "name:" << name; + + Q_EMIT q_ptr->nameRegistrationEnded(static_cast<NameDirectory::RegisterNameStatus>(status), name); +} + +// Registered Name found +void +NameDirectoryPrivate::slotRegisteredNameFound(const QString& accountId, + int status, + const QString& address, + const QString& name) +{ + switch (static_cast<NameDirectory::LookupStatus>(status)) { + case NameDirectory::LookupStatus::INVALID_NAME: + qDebug() << "lookup name is INVALID:" << name << accountId; + break; + case NameDirectory::LookupStatus::NOT_FOUND: + qDebug() << "lookup name NOT FOUND:" << name << accountId; + break; + case NameDirectory::LookupStatus::ERROR: + qDebug() << "lookup name ERROR:" << name << accountId; + break; + case NameDirectory::LookupStatus::SUCCESS: + break; + } + + Q_EMIT q_ptr->registeredNameFound(static_cast<NameDirectory::LookupStatus>(status), address, name); +} + +// Export account has ended with pin generated +void +NameDirectoryPrivate::slotExportOnRingEnded(const QString& accountId, int status, const QString& pin) +{ + qDebug() << "Export on ring ended for account: " << accountId << "status: " << status + << "PIN: " << pin; + + Q_EMIT q_ptr->exportOnRingEnded(static_cast<NameDirectory::ExportOnRingStatus>(status), pin); +} + +// Lookup a name +bool +NameDirectory::lookupName(const QString& nameServiceURL, const QString& name) const +{ + return ConfigurationManager::instance().lookupName("", nameServiceURL, name); +} + +// Lookup an address +bool +NameDirectory::lookupAddress(const QString& nameServiceURL, const QString& address) const +{ + return ConfigurationManager::instance().lookupAddress("", nameServiceURL, address); +} + +NameDirectory::~NameDirectory() +{ + delete d_ptr; +} diff --git a/src/libclient/namedirectory.h b/src/libclient/namedirectory.h new file mode 100644 index 0000000000000000000000000000000000000000..946150b9b2c84b05fe03f09aad9a2fde6f652f17 --- /dev/null +++ b/src/libclient/namedirectory.h @@ -0,0 +1,76 @@ +/**************************************************************************** + * Copyright (C) 2016-2022 Savoir-faire Linux Inc. * + * Author : Alexandre Viau <alexandre.viau@savoirfairelinux.com> * + * Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#include "typedefs.h" + +class NameDirectoryPrivate; +class Account; + +class LIB_EXPORT NameDirectory : public QObject +{ + Q_OBJECT + Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") +public: + // Register name status + enum class RegisterNameStatus { + SUCCESS = 0, + WRONG_PASSWORD = 1, + INVALID_NAME = 2, + ALREADY_TAKEN = 3, + NETWORK_ERROR = 4 + }; + Q_ENUM(RegisterNameStatus) + + // Lookup name status + enum class LookupStatus { SUCCESS = 0, INVALID_NAME = 1, NOT_FOUND = 2, ERROR = 3 }; + Q_ENUM(LookupStatus) + + enum class ExportOnRingStatus { SUCCESS = 0, WRONG_PASSWORD = 1, NETWORK_ERROR = 2, INVALID }; + Q_ENUM(ExportOnRingStatus) + + // Singleton + static NameDirectory& instance(); + + // Lookup + Q_INVOKABLE bool lookupName(const QString& nameServiceURL, const QString& name) const; + Q_INVOKABLE bool lookupAddress(const QString& nameServiceURL, const QString& address) const; + +private: + // Constructors & Destructors + explicit NameDirectory(); + virtual ~NameDirectory(); + + NameDirectoryPrivate* d_ptr; + Q_DECLARE_PRIVATE(NameDirectory) + Q_DISABLE_COPY(NameDirectory) + +Q_SIGNALS: + /// RegisterName has ended + void nameRegistrationEnded(NameDirectory::RegisterNameStatus status, const QString& name); + + /// Name or address lookup has completed + void registeredNameFound(NameDirectory::LookupStatus status, + const QString& address, + const QString& name); + + // Export account has ended with pin generated + void exportOnRingEnded(NameDirectory::ExportOnRingStatus status, const QString& pin); +}; +Q_DECLARE_METATYPE(NameDirectory*) diff --git a/src/libclient/newaccountmodel.cpp b/src/libclient/newaccountmodel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..871f0c7c9b778d75171a75afae63dcf13339b0f9 --- /dev/null +++ b/src/libclient/newaccountmodel.cpp @@ -0,0 +1,1235 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * Author: Kateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com> * + * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#include "api/newaccountmodel.h" + +// new LRC +#include "api/lrc.h" +#include "api/contactmodel.h" +#include "api/conversationmodel.h" +#include "api/peerdiscoverymodel.h" +#include "api/newcallmodel.h" +#include "api/newcodecmodel.h" +#include "api/newdevicemodel.h" +#include "api/behaviorcontroller.h" +#include "api/datatransfermodel.h" +#include "authority/storagehelper.h" +#include "callbackshandler.h" +#include "database.h" +#include "vcard.h" + +// old LRC +#include "api/profile.h" +#include "qtwrapper/conversions_wrap.hpp" + +// Dbus +#include "dbus/configurationmanager.h" + +// daemon +#include <account_const.h> + +// qt +#include <QtGui/QPixmap> +#include <QtGui/QImage> +#include <QtCore/QBuffer> + +#include <atomic> + +namespace lrc { + +using namespace api; + +class NewAccountModelPimpl : public QObject +{ + Q_OBJECT +public: + NewAccountModelPimpl(NewAccountModel& linked, + Lrc& lrc, + const CallbacksHandler& callbackHandler, + const BehaviorController& behaviorController, + MigrationCb& willMigrateCb, + MigrationCb& didMigrateCb); + ~NewAccountModelPimpl(); + + using AccountInfoDbMap = std::map<QString, std::pair<account::Info, std::shared_ptr<Database>>>; + + NewAccountModel& linked; + Lrc& lrc; + const CallbacksHandler& callbacksHandler; + const BehaviorController& behaviorController; + AccountInfoDbMap accounts; + + // Synchronization tools + std::mutex m_mutex_account; + std::mutex m_mutex_account_removal; + std::condition_variable m_condVar_account_removal; + std::atomic_bool username_changed; + QString new_username; + + /** + * Add the profile information from an account to the db then add it to accounts. + * @param accountId + * @param db an optional migrated database object + * @note this method get details for an account from the daemon. + */ + void addToAccounts(const QString& accountId, std::shared_ptr<Database> db = nullptr); + + /** + * Remove account from accounts list. Emit accountRemoved. + * @param accountId + */ + void removeFromAccounts(const QString& accountId); + + /** + * Sync changes to the accounts list with the lrc. + */ + void updateAccounts(); + + /** + * Update accountInfo with details from daemon + * @param account account to update + */ + void updateAccountDetails(account::Info& account); + + /** + * get a modifiable account informations associated to an accountId. + * @param accountId. + * @return a account::Info& structure. + */ + account::Info& getAccountInfo(const QString& accountId); + +public Q_SLOTS: + + /** + * Emit accountStatusChanged. + * @param accountId + * @param status + */ + void slotAccountStatusChanged(const QString& accountID, const api::account::Status status); + + /** + * Emit exportOnRingEnded. + * @param accountId + * @param status + * @param pin + */ + void slotExportOnRingEnded(const QString& accountID, int status, const QString& pin); + + /** + * @param accountId + * @param details + */ + void slotAccountDetailsChanged(const QString& accountID, const MapStringString& details); + + /** + * @param accountId + * @param details + */ + void slotVolatileAccountDetailsChanged(const QString& accountID, const MapStringString& details); + + /** + * Emit nameRegistrationEnded + * @param accountId + * @param status + * @param name + */ + void slotNameRegistrationEnded(const QString& accountId, int status, const QString& name); + + /** + * Emit registeredNameFound + * @param accountId + * @param status + * @param address + * @param name + */ + void slotRegisteredNameFound(const QString& accountId, + int status, + const QString& address, + const QString& name); + + /** + * Emit migrationEnded + * @param accountId + * @param ok + */ + void slotMigrationEnded(const QString& accountId, bool ok); + + /** + * Emit accountProfileReceived + * @param accountId + * @param displayName + * @param userPhoto + */ + void slotAccountProfileReceived(const QString& accountId, + const QString& displayName, + const QString& userPhoto); +}; + +NewAccountModel::NewAccountModel(Lrc& lrc, + const CallbacksHandler& callbacksHandler, + const BehaviorController& behaviorController, + MigrationCb& willMigrateCb, + MigrationCb& didMigrateCb) + : QObject(nullptr) + , pimpl_(std::make_unique<NewAccountModelPimpl>(*this, + lrc, + callbacksHandler, + behaviorController, + willMigrateCb, + didMigrateCb)) +{} + +NewAccountModel::~NewAccountModel() {} + +QStringList +NewAccountModel::getAccountList() const +{ + QStringList filteredAccountIds; + const QStringList accountIds = ConfigurationManager::instance().getAccountList(); + + for (auto const& id : accountIds) { + auto account = pimpl_->accounts.find(id); + // Do not include accounts flagged for removal + if (account != pimpl_->accounts.end() && account->second.first.valid) + filteredAccountIds.push_back(id); + } + + return filteredAccountIds; +} + +void +NewAccountModel::setAccountEnabled(const QString& accountId, bool enabled) const +{ + auto& accountInfo = pimpl_->getAccountInfo(accountId); + accountInfo.enabled = enabled; + ConfigurationManager::instance().sendRegister(accountId, enabled); +} + +void +NewAccountModel::setAccountConfig(const QString& accountId, + const account::ConfProperties_t& confProperties) const +{ + auto& accountInfo = pimpl_->getAccountInfo(accountId); + auto& configurationManager = ConfigurationManager::instance(); + MapStringString details = confProperties.toDetails(); + // Set values from Info. No need to include ID and TYPE. SIP accounts may modify the USERNAME + // TODO: move these into the ConfProperties_t struct ? + using namespace DRing::Account; + details[ConfProperties::ENABLED] = accountInfo.enabled ? QString("true") : QString("false"); + details[ConfProperties::ALIAS] = accountInfo.profileInfo.alias; + details[ConfProperties::DISPLAYNAME] = accountInfo.profileInfo.alias; + details[ConfProperties::TYPE] = (accountInfo.profileInfo.type == profile::Type::JAMI) + ? QString(ProtocolNames::RING) + : QString(ProtocolNames::SIP); + if (accountInfo.profileInfo.type == profile::Type::JAMI) { + details[ConfProperties::USERNAME] = accountInfo.profileInfo.uri; + } else if (accountInfo.profileInfo.type == profile::Type::SIP) { + VectorMapStringString finalCred; + + MapStringString credentials; + credentials[ConfProperties::USERNAME] = confProperties.username; + credentials[ConfProperties::PASSWORD] = confProperties.password; + credentials[ConfProperties::REALM] = confProperties.realm.isEmpty() ? "*" + : confProperties.realm; + + auto credentialsVec = confProperties.credentials; + credentialsVec[0] = credentials; + for (auto const& i : credentialsVec) { + QMap<QString, QString> credMap; + for (auto const& j : i.toStdMap()) { + credMap[j.first] = j.second; + } + finalCred.append(credMap); + } + + ConfigurationManager::instance().setCredentials(accountId, finalCred); + details[ConfProperties::USERNAME] = confProperties.username; + accountInfo.confProperties.credentials.swap(credentialsVec); + } + configurationManager.setAccountDetails(accountId, details); +} + +account::ConfProperties_t +NewAccountModel::getAccountConfig(const QString& accountId) const +{ + return getAccountInfo(accountId).confProperties; +} + +void +NewAccountModel::setAlias(const QString& accountId, const QString& alias) +{ + auto& accountInfo = pimpl_->getAccountInfo(accountId); + if (accountInfo.profileInfo.alias == alias) + return; + accountInfo.profileInfo.alias = alias; + + authority::storage::createOrUpdateProfile(accountInfo.id, accountInfo.profileInfo); + + Q_EMIT profileUpdated(accountId); +} + +void +NewAccountModel::setAvatar(const QString& accountId, const QString& avatar) +{ + auto& accountInfo = pimpl_->getAccountInfo(accountId); + if (accountInfo.profileInfo.avatar == avatar) + return; + accountInfo.profileInfo.avatar = avatar; + + authority::storage::createOrUpdateProfile(accountInfo.id, accountInfo.profileInfo); + + Q_EMIT profileUpdated(accountId); +} + +bool +NewAccountModel::registerName(const QString& accountId, + const QString& password, + const QString& username) +{ + return ConfigurationManager::instance().registerName(accountId, password, username); +} + +bool +NewAccountModel::exportToFile(const QString& accountId, + const QString& path, + const QString& password) const +{ + return ConfigurationManager::instance().exportToFile(accountId, path, password); +} + +bool +NewAccountModel::exportOnRing(const QString& accountId, const QString& password) const +{ + return ConfigurationManager::instance().exportOnRing(accountId, password); +} + +void +NewAccountModel::removeAccount(const QString& accountId) const +{ + auto account = pimpl_->accounts.find(accountId); + if (account == pimpl_->accounts.end()) { + return; + } + + // Close db here for its removal + account->second.second->close(); + ConfigurationManager::instance().removeAccount(accountId); +} + +bool +NewAccountModel::changeAccountPassword(const QString& accountId, + const QString& currentPassword, + const QString& newPassword) const +{ + return ConfigurationManager::instance().changeAccountPassword(accountId, + currentPassword, + newPassword); +} + +void +NewAccountModel::flagFreeable(const QString& accountId) const +{ + auto account = pimpl_->accounts.find(accountId); + if (account == pimpl_->accounts.end()) + throw std::out_of_range("NewAccountModel::flagFreeable, can't find " + + accountId.toStdString()); + + { + std::lock_guard<std::mutex> lock(pimpl_->m_mutex_account_removal); + account->second.first.freeable = true; + } + pimpl_->m_condVar_account_removal.notify_all(); +} + +const account::Info& +NewAccountModel::getAccountInfo(const QString& accountId) const +{ + auto accountInfo = pimpl_->accounts.find(accountId); + if (accountInfo == pimpl_->accounts.end()) + throw std::out_of_range("NewAccountModel::getAccountInfo, can't find " + + accountId.toStdString()); + + return accountInfo->second.first; +} + +NewAccountModelPimpl::NewAccountModelPimpl(NewAccountModel& linked, + Lrc& lrc, + const CallbacksHandler& callbacksHandler, + const BehaviorController& behaviorController, + MigrationCb& willMigrateCb, + MigrationCb& didMigrateCb) + : linked(linked) + , lrc {lrc} + , behaviorController(behaviorController) + , callbacksHandler(callbacksHandler) + , username_changed(false) +{ + const QStringList accountIds = ConfigurationManager::instance().getAccountList(); + + // NOTE: If the daemon is down, but dbus answered, id can contains + // "Remote peer disconnected", "The name is not activable", etc. + // So avoid to migrate useless directories. + for (auto& id : accountIds) + if (id.indexOf(" ") != -1) { + qWarning() << "Invalid dbus answer. Daemon not running"; + return; + } + + auto accountDbs = authority::storage::migrateIfNeeded(accountIds, willMigrateCb, didMigrateCb); + for (const auto& id : accountIds) { + addToAccounts(id, accountDbs.at(accountIds.indexOf(id))); + } + + connect(&callbacksHandler, + &CallbacksHandler::accountsChanged, + this, + &NewAccountModelPimpl::updateAccounts); + connect(&callbacksHandler, + &CallbacksHandler::accountStatusChanged, + this, + &NewAccountModelPimpl::slotAccountStatusChanged); + connect(&callbacksHandler, + &CallbacksHandler::accountDetailsChanged, + this, + &NewAccountModelPimpl::slotAccountDetailsChanged); + connect(&callbacksHandler, + &CallbacksHandler::volatileAccountDetailsChanged, + this, + &NewAccountModelPimpl::slotVolatileAccountDetailsChanged); + connect(&callbacksHandler, + &CallbacksHandler::exportOnRingEnded, + this, + &NewAccountModelPimpl::slotExportOnRingEnded); + connect(&callbacksHandler, + &CallbacksHandler::nameRegistrationEnded, + this, + &NewAccountModelPimpl::slotNameRegistrationEnded); + connect(&callbacksHandler, + &CallbacksHandler::registeredNameFound, + this, + &NewAccountModelPimpl::slotRegisteredNameFound); + connect(&callbacksHandler, + &CallbacksHandler::migrationEnded, + this, + &NewAccountModelPimpl::slotMigrationEnded); + connect(&callbacksHandler, + &CallbacksHandler::accountProfileReceived, + this, + &NewAccountModelPimpl::slotAccountProfileReceived); +} + +NewAccountModelPimpl::~NewAccountModelPimpl() {} + +void +NewAccountModelPimpl::updateAccounts() +{ + qDebug() << "Syncing lrc accounts list with the daemon"; + ConfigurationManagerInterface& configurationManager = ConfigurationManager::instance(); + QStringList accountIds = configurationManager.getAccountList(); + + // Detect removed accounts + QStringList toBeRemoved; + for (auto& it : accounts) { + auto& accountInfo = it.second.first; + if (!accountIds.contains(accountInfo.id)) { + qDebug() << QString("detected account removal %1").arg(accountInfo.id); + toBeRemoved.push_back(accountInfo.id); + } + } + + for (auto it = toBeRemoved.begin(); it != toBeRemoved.end(); ++it) { + removeFromAccounts(*it); + } + + // Detect new accounts + for (auto& id : accountIds) { + auto account = accounts.find(id); + // NOTE: If the daemon is down, but dbus answered, id can contains + // "Remote peer disconnected", "The name is not activable", etc. + // So avoid to create useless directories. + if (account == accounts.end() && id.indexOf(" ") == -1) { + qWarning() << QString("detected new account %1").arg(id); + addToAccounts(id); + auto updatedAccount = accounts.find(id); + if (updatedAccount == accounts.end()) { + return; + } + if (updatedAccount->second.first.profileInfo.type == profile::Type::SIP) { + // NOTE: At this point, a SIP account is ready, but not a Ring + // account. Indeed, the keys are not generated at this point. + // See slotAccountStatusChanged for more details. + Q_EMIT linked.accountAdded(id); + } + } + } +} + +void +NewAccountModelPimpl::updateAccountDetails(account::Info& accountInfo) +{ + // Fill account::Info struct with details from daemon + MapStringString details = ConfigurationManager::instance().getAccountDetails(accountInfo.id); + accountInfo.fromDetails(details); + + // Fill account::Info::confProperties credentials + VectorMapStringString credGet = ConfigurationManager::instance().getCredentials(accountInfo.id); + VectorMapStringString credToStore; + for (auto const& i : std::vector<MapStringString>(credGet.begin(), credGet.end())) { + MapStringString credMap; + for (auto const& j : i.toStdMap()) { + credMap[j.first] = j.second; + } + credToStore.push_back(credMap); + } + + accountInfo.confProperties.credentials.swap(credToStore); + + MapStringString volatileDetails = ConfigurationManager::instance().getVolatileAccountDetails( + accountInfo.id); + QString daemonStatus = volatileDetails[DRing::Account::ConfProperties::Registration::STATUS]; + accountInfo.status = lrc::api::account::to_status(daemonStatus); +} + +account::Info& +NewAccountModelPimpl::getAccountInfo(const QString& accountId) +{ + auto account = accounts.find(accountId); + if (account == accounts.end()) { + throw std::out_of_range("NewAccountModelPimpl::getAccountInfo, can't find " + + accountId.toStdString()); + } + return account->second.first; +} + +void +NewAccountModelPimpl::slotAccountStatusChanged(const QString& accountID, + const api::account::Status status) +{ + if (status == api::account::Status::INVALID) { + Q_EMIT linked.invalidAccountDetected(accountID); + return; + } + auto it = accounts.find(accountID); + + // If account is not in the map yet, don't add it, it is updateAccounts's job + if (it == accounts.end()) { + return; + } + + auto& accountInfo = it->second.first; + + if (accountInfo.profileInfo.type != profile::Type::SIP) { + if (status != api::account::Status::INITIALIZING + && accountInfo.status == api::account::Status::INITIALIZING) { + // Detect when a new account is generated (keys are ready). During + // the generation, a Ring account got the "INITIALIZING" status. + // When keys are generated, the status will change. + // The account is already added and initialized. Just update details from daemon + updateAccountDetails(accountInfo); + // This will load swarms as the account was not loaded before. + accountInfo.conversationModel->initConversations(); + Q_EMIT linked.accountAdded(accountID); + } else if (!accountInfo.profileInfo.uri.isEmpty()) { + accountInfo.status = status; + Q_EMIT linked.accountStatusChanged(accountID); + } + } else { + accountInfo.status = status; + Q_EMIT linked.accountStatusChanged(accountID); + } +} + +void +NewAccountModelPimpl::slotAccountDetailsChanged(const QString& accountId, + const MapStringString& details) +{ + auto account = accounts.find(accountId); + if (account == accounts.end()) { + throw std::out_of_range("NewAccountModelPimpl::slotAccountDetailsChanged, can't find " + + accountId.toStdString()); + } + auto& accountInfo = account->second.first; + accountInfo.fromDetails(details); + if (username_changed) { + username_changed = false; + accountInfo.registeredName = new_username; + Q_EMIT linked.profileUpdated(accountId); + } + // TODO: Remove accountStatusChanged here. + Q_EMIT linked.accountStatusChanged(accountId); + Q_EMIT linked.accountDetailsChanged(accountId); +} + +void +NewAccountModelPimpl::slotVolatileAccountDetailsChanged(const QString& accountId, + const MapStringString& details) +{ + auto account = accounts.find(accountId); + if (account == accounts.end()) { + qWarning() << "NewAccountModelPimpl::slotVolatileAccountDetailsChanged, can't find " + << accountId; + return; + } + auto& accountInfo = account->second.first; + + auto new_usernameIt = details.find(DRing::Account::VolatileProperties::REGISTERED_NAME); + if (new_usernameIt == details.end()) + return; + accountInfo.registeredName = new_usernameIt.value(); + Q_EMIT linked.profileUpdated(accountId); +} + +void +NewAccountModelPimpl::slotExportOnRingEnded(const QString& accountID, int status, const QString& pin) +{ + account::ExportOnRingStatus convertedStatus = account::ExportOnRingStatus::INVALID; + switch (status) { + case 0: + convertedStatus = account::ExportOnRingStatus::SUCCESS; + break; + case 1: + convertedStatus = account::ExportOnRingStatus::WRONG_PASSWORD; + break; + case 2: + convertedStatus = account::ExportOnRingStatus::NETWORK_ERROR; + break; + default: + break; + } + Q_EMIT linked.exportOnRingEnded(accountID, convertedStatus, pin); +} + +void +NewAccountModelPimpl::slotNameRegistrationEnded(const QString& accountId, + int status, + const QString& name) +{ + account::RegisterNameStatus convertedStatus = account::RegisterNameStatus::INVALID; + switch (status) { + case 0: { + convertedStatus = account::RegisterNameStatus::SUCCESS; + auto account = accounts.find(accountId); + if (account != accounts.end() && account->second.first.registeredName.isEmpty()) { + auto conf = linked.getAccountConfig(accountId); + username_changed = true; + new_username = name; + linked.setAccountConfig(accountId, conf); + } + break; + } + case 1: + convertedStatus = account::RegisterNameStatus::WRONG_PASSWORD; + break; + case 2: + convertedStatus = account::RegisterNameStatus::INVALID_NAME; + break; + case 3: + convertedStatus = account::RegisterNameStatus::ALREADY_TAKEN; + break; + case 4: + convertedStatus = account::RegisterNameStatus::NETWORK_ERROR; + break; + default: + break; + } + Q_EMIT linked.nameRegistrationEnded(accountId, convertedStatus, name); +} + +void +NewAccountModelPimpl::slotRegisteredNameFound(const QString& accountId, + int status, + const QString& address, + const QString& name) +{ + account::LookupStatus convertedStatus = account::LookupStatus::INVALID; + switch (status) { + case 0: + convertedStatus = account::LookupStatus::SUCCESS; + break; + case 1: + convertedStatus = account::LookupStatus::INVALID_NAME; + break; + case 2: + convertedStatus = account::LookupStatus::NOT_FOUND; + break; + case 3: + convertedStatus = account::LookupStatus::ERROR; + break; + default: + break; + } + Q_EMIT linked.registeredNameFound(accountId, convertedStatus, address, name); +} + +void +NewAccountModelPimpl::slotMigrationEnded(const QString& accountId, bool ok) +{ + if (ok) { + auto it = accounts.find(accountId); + if (it == accounts.end()) { + addToAccounts(accountId); + return; + } + auto& accountInfo = it->second.first; + MapStringString details = ConfigurationManager::instance().getAccountDetails(accountId); + accountInfo.fromDetails(details); + MapStringString volatileDetails = ConfigurationManager::instance().getVolatileAccountDetails( + accountId); + QString daemonStatus = volatileDetails[DRing::Account::ConfProperties::Registration::STATUS]; + accountInfo.status = lrc::api::account::to_status(daemonStatus); + } + Q_EMIT linked.migrationEnded(accountId, ok); +} + +void +NewAccountModelPimpl::slotAccountProfileReceived(const QString& accountId, + const QString& displayName, + const QString& userPhoto) +{ + auto account = accounts.find(accountId); + if (account == accounts.end()) + return; + auto& accountInfo = account->second.first; + accountInfo.profileInfo.avatar = userPhoto; + accountInfo.profileInfo.alias = displayName; + + authority::storage::createOrUpdateProfile(accountInfo.id, accountInfo.profileInfo); + + Q_EMIT linked.profileUpdated(accountId); +} + +void +NewAccountModelPimpl::addToAccounts(const QString& accountId, std::shared_ptr<Database> db) +{ + if (db == nullptr) { + try { + auto appPath = authority::storage::getPath(); + auto dbName = accountId + "/history"; + db = DatabaseFactory::create<Database>(dbName, appPath); + // create the profiles path if necessary + QDir profilesDir(appPath + accountId + "/profiles"); + if (!profilesDir.exists()) { + profilesDir.mkpath("."); + } + } catch (const std::runtime_error& e) { + qWarning() << e.what(); + return; + } + } + + auto it = accounts.emplace(accountId, std::make_pair(account::Info(), db)); + + if (!it.second) { + qWarning("failed to add new account: id already present in map"); + return; + } + + // Init profile + account::Info& newAccInfo = (it.first)->second.first; + newAccInfo.id = accountId; + newAccInfo.profileInfo.avatar = authority::storage::getAccountAvatar(accountId); + updateAccountDetails(newAccInfo); + + // Init models for this account + newAccInfo.accountModel = &linked; + newAccInfo.callModel = std::make_unique<NewCallModel>(newAccInfo, + lrc, + callbacksHandler, + behaviorController); + newAccInfo.contactModel = std::make_unique<ContactModel>(newAccInfo, + *db, + callbacksHandler, + behaviorController); + newAccInfo.conversationModel = std::make_unique<ConversationModel>(newAccInfo, + lrc, + *db, + callbacksHandler, + behaviorController); + newAccInfo.peerDiscoveryModel = std::make_unique<PeerDiscoveryModel>(callbacksHandler, + accountId); + newAccInfo.deviceModel = std::make_unique<NewDeviceModel>(newAccInfo, callbacksHandler); + newAccInfo.codecModel = std::make_unique<NewCodecModel>(newAccInfo, callbacksHandler); + newAccInfo.dataTransferModel = std::make_unique<DataTransferModel>(); +} + +void +NewAccountModelPimpl::removeFromAccounts(const QString& accountId) +{ + /* Update db before waiting for the client to stop using the structs is fine + as long as we don't free anything */ + auto account = accounts.find(accountId); + if (account == accounts.end()) { + return; + } + auto& accountInfo = account->second.first; + if (accountInfo.profileInfo.type == profile::Type::SIP) { + auto accountDir = QDir(authority::storage::getPath() + accountId); + accountDir.removeRecursively(); + } + + /* Inform client about account removal. Do *not* free account structures + before we are sure that the client stopped using it, otherwise we might + get into use-after-free troubles. */ + accountInfo.valid = false; + Q_EMIT linked.accountRemoved(accountId); + +#ifdef CHK_FREEABLE_BEFORE_ERASE_ACCOUNT + std::unique_lock<std::mutex> lock(m_mutex_account_removal); + // Wait for client to stop using old account structs + m_condVar_account_removal.wait(lock, [&]() { return accounts[accountId].first.freeable; }); + lock.unlock(); +#endif + + // Now we can free them + accounts.erase(accountId); +} + +void +account::Info::fromDetails(const MapStringString& details) +{ + using namespace DRing::Account; + const MapStringString volatileDetails = ConfigurationManager::instance() + .getVolatileAccountDetails(id); + + // General + if (details[ConfProperties::TYPE] != "") + profileInfo.type = details[ConfProperties::TYPE] == QString(ProtocolNames::RING) + ? profile::Type::JAMI + : profile::Type::SIP; + registeredName = profileInfo.type == profile::Type::JAMI + ? volatileDetails[VolatileProperties::REGISTERED_NAME] + : ""; + profileInfo.alias = details[ConfProperties::DISPLAYNAME]; + enabled = toBool(details[ConfProperties::ENABLED]); + confProperties.mailbox = details[ConfProperties::MAILBOX]; + confProperties.dtmfType = details[ConfProperties::DTMF_TYPE]; + confProperties.autoAnswer = toBool(details[ConfProperties::AUTOANSWER]); + confProperties.sendReadReceipt = toBool(details[ConfProperties::SENDREADRECEIPT]); + confProperties.isRendezVous = toBool(details[ConfProperties::ISRENDEZVOUS]); + confProperties.activeCallLimit = toInt(details[ConfProperties::ACTIVE_CALL_LIMIT]); + confProperties.hostname = details[ConfProperties::HOSTNAME]; + profileInfo.uri = (profileInfo.type == profile::Type::JAMI + and details[ConfProperties::USERNAME].contains("ring:")) + ? QString(details[ConfProperties::USERNAME]).remove(QString("ring:")) + : details[ConfProperties::USERNAME]; + confProperties.username = details[ConfProperties::USERNAME]; + confProperties.routeset = details[ConfProperties::ROUTE]; + confProperties.password = details[ConfProperties::PASSWORD]; + confProperties.realm = details[ConfProperties::REALM]; + confProperties.localInterface = details[ConfProperties::LOCAL_INTERFACE]; + confProperties.deviceId = details[ConfProperties::DEVICE_ID]; + confProperties.deviceName = details[ConfProperties::DEVICE_NAME]; + confProperties.publishedSameAsLocal = toBool(details[ConfProperties::PUBLISHED_SAMEAS_LOCAL]); + confProperties.localPort = toInt(details[ConfProperties::LOCAL_PORT]); + confProperties.publishedPort = toInt(details[ConfProperties::PUBLISHED_PORT]); + confProperties.publishedAddress = details[ConfProperties::PUBLISHED_ADDRESS]; + confProperties.userAgent = details[ConfProperties::USER_AGENT]; + confProperties.upnpEnabled = toBool(details[ConfProperties::UPNP_ENABLED]); + confProperties.hasCustomUserAgent = toBool(details[ConfProperties::HAS_CUSTOM_USER_AGENT]); + confProperties.allowIncoming = toBool(details[ConfProperties::ALLOW_CERT_FROM_HISTORY]) + | toBool(details[ConfProperties::ALLOW_CERT_FROM_CONTACT]) + | toBool(details[ConfProperties::ALLOW_CERT_FROM_TRUSTED]); + confProperties.allowIPAutoRewrite = toBool(details[ConfProperties::ACCOUNT_IP_AUTO_REWRITE]); + confProperties.archivePassword = details[ConfProperties::ARCHIVE_PASSWORD]; + confProperties.archiveHasPassword = toBool(details[ConfProperties::ARCHIVE_HAS_PASSWORD]); + confProperties.archivePath = details[ConfProperties::ARCHIVE_PATH]; + confProperties.archivePin = details[ConfProperties::ARCHIVE_PIN]; + confProperties.proxyEnabled = toBool(details[ConfProperties::PROXY_ENABLED]); + confProperties.proxyServer = details[ConfProperties::PROXY_SERVER]; + confProperties.proxyPushToken = details[ConfProperties::PROXY_PUSH_TOKEN]; + confProperties.peerDiscovery = toBool(details[ConfProperties::DHT_PEER_DISCOVERY]); + confProperties.accountDiscovery = toBool(details[ConfProperties::ACCOUNT_PEER_DISCOVERY]); + confProperties.accountPublish = toBool(details[ConfProperties::ACCOUNT_PUBLISH]); + confProperties.keepAliveEnabled = toBool(details[ConfProperties::KEEP_ALIVE_ENABLED]); + confProperties.bootstrapListUrl = QString(details[ConfProperties::BOOTSTRAP_LIST_URL]); + confProperties.dhtProxyListUrl = QString(details[ConfProperties::DHT_PROXY_LIST_URL]); + confProperties.defaultModerators = QString(details[ConfProperties::DEFAULT_MODERATORS]); + confProperties.localModeratorsEnabled = toBool( + details[ConfProperties::LOCAL_MODERATORS_ENABLED]); + // Audio + confProperties.Audio.audioPortMax = toInt(details[ConfProperties::Audio::PORT_MAX]); + confProperties.Audio.audioPortMin = toInt(details[ConfProperties::Audio::PORT_MIN]); + // Video + confProperties.Video.videoEnabled = toBool(details[ConfProperties::Video::ENABLED]); + confProperties.Video.videoPortMax = toInt(details[ConfProperties::Video::PORT_MAX]); + confProperties.Video.videoPortMin = toInt(details[ConfProperties::Video::PORT_MIN]); + // STUN + confProperties.STUN.server = details[ConfProperties::STUN::SERVER]; + confProperties.STUN.enable = toBool(details[ConfProperties::STUN::ENABLED]); + // TURN + confProperties.TURN.server = details[ConfProperties::TURN::SERVER]; + confProperties.TURN.enable = toBool(details[ConfProperties::TURN::ENABLED]); + confProperties.TURN.username = details[ConfProperties::TURN::SERVER_UNAME]; + confProperties.TURN.password = details[ConfProperties::TURN::SERVER_PWD]; + confProperties.TURN.realm = details[ConfProperties::TURN::SERVER_REALM]; + // Presence + confProperties.Presence.presencePublishSupported = toBool( + details[ConfProperties::Presence::SUPPORT_PUBLISH]); + confProperties.Presence.presenceSubscribeSupported = toBool( + details[ConfProperties::Presence::SUPPORT_SUBSCRIBE]); + confProperties.Presence.presenceEnabled = toBool(details[ConfProperties::Presence::ENABLED]); + // Ringtone + confProperties.Ringtone.ringtonePath = details[ConfProperties::Ringtone::PATH]; + confProperties.Ringtone.ringtoneEnabled = toBool(details[ConfProperties::Ringtone::ENABLED]); + // SRTP + confProperties.SRTP.keyExchange = details[ConfProperties::SRTP::KEY_EXCHANGE].isEmpty() + ? account::KeyExchangeProtocol::NONE + : account::KeyExchangeProtocol::SDES; + confProperties.SRTP.enable = toBool(details[ConfProperties::SRTP::ENABLED]); + confProperties.SRTP.rtpFallback = toBool(details[ConfProperties::SRTP::RTP_FALLBACK]); + // TLS + confProperties.TLS.listenerPort = toInt(details[ConfProperties::TLS::LISTENER_PORT]); + confProperties.TLS.enable = details[ConfProperties::TYPE] == QString(ProtocolNames::RING) + ? true + : toBool(details[ConfProperties::TLS::ENABLED]); + confProperties.TLS.port = toInt(details[ConfProperties::TLS::PORT]); + confProperties.TLS.certificateListFile = details[ConfProperties::TLS::CA_LIST_FILE]; + confProperties.TLS.certificateFile = details[ConfProperties::TLS::CERTIFICATE_FILE]; + confProperties.TLS.privateKeyFile = details[ConfProperties::TLS::PRIVATE_KEY_FILE]; + confProperties.TLS.password = details[ConfProperties::TLS::PASSWORD]; + auto method = toStdString(details[ConfProperties::TLS::METHOD]); + if (method == "TLSv1") { + confProperties.TLS.method = account::TlsMethod::TLSv1; + } else if (method == "TLSv1.1") { + confProperties.TLS.method = account::TlsMethod::TLSv1_1; + } else if (method == "TLSv1.2") { + confProperties.TLS.method = account::TlsMethod::TLSv1_2; + } else { + confProperties.TLS.method = account::TlsMethod::DEFAULT; + } + confProperties.TLS.ciphers = details[ConfProperties::TLS::CIPHERS]; + confProperties.TLS.serverName = details[ConfProperties::TLS::SERVER_NAME]; + confProperties.TLS.verifyServer = toBool(details[ConfProperties::TLS::VERIFY_SERVER]); + confProperties.TLS.verifyClient = toBool(details[ConfProperties::TLS::VERIFY_CLIENT]); + confProperties.TLS.requireClientCertificate = toBool( + details[ConfProperties::TLS::REQUIRE_CLIENT_CERTIFICATE]); + confProperties.TLS.negotiationTimeoutSec = toInt( + details[ConfProperties::TLS::NEGOTIATION_TIMEOUT_SEC]); + // DHT + confProperties.DHT.port = toInt(details[ConfProperties::DHT::PORT]); + confProperties.DHT.PublicInCalls = toBool(details[ConfProperties::DHT::PUBLIC_IN_CALLS]); + confProperties.DHT.AllowFromTrusted = toBool(details[ConfProperties::DHT::ALLOW_FROM_TRUSTED]); + // RingNS + confProperties.RingNS.uri = details[ConfProperties::RingNS::URI]; + confProperties.RingNS.account = details[ConfProperties::RingNS::ACCOUNT]; + // Registration + confProperties.Registration.expire = toInt(details[ConfProperties::Registration::EXPIRE]); + // Jams + confProperties.managerUri = details[ConfProperties::MANAGER_URI]; + confProperties.managerUsername = details[ConfProperties::MANAGER_USERNAME]; +} + +MapStringString +account::ConfProperties_t::toDetails() const +{ + using namespace DRing::Account; + MapStringString details; + // General + details[ConfProperties::MAILBOX] = this->mailbox; + details[ConfProperties::DTMF_TYPE] = this->dtmfType; + details[ConfProperties::AUTOANSWER] = toQString(this->autoAnswer); + details[ConfProperties::SENDREADRECEIPT] = toQString(this->sendReadReceipt); + details[ConfProperties::ISRENDEZVOUS] = toQString(this->isRendezVous); + details[ConfProperties::ACTIVE_CALL_LIMIT] = toQString(this->activeCallLimit); + details[ConfProperties::HOSTNAME] = this->hostname; + details[ConfProperties::ROUTE] = this->routeset; + details[ConfProperties::PASSWORD] = this->password; + details[ConfProperties::REALM] = this->realm; + details[ConfProperties::DEVICE_ID] = this->deviceId; + details[ConfProperties::DEVICE_NAME] = this->deviceName; + details[ConfProperties::LOCAL_INTERFACE] = this->localInterface; + details[ConfProperties::PUBLISHED_SAMEAS_LOCAL] = toQString(this->publishedSameAsLocal); + details[ConfProperties::LOCAL_PORT] = toQString(this->localPort); + details[ConfProperties::PUBLISHED_PORT] = toQString(this->publishedPort); + details[ConfProperties::PUBLISHED_ADDRESS] = this->publishedAddress; + details[ConfProperties::USER_AGENT] = this->userAgent; + details[ConfProperties::UPNP_ENABLED] = toQString(this->upnpEnabled); + details[ConfProperties::HAS_CUSTOM_USER_AGENT] = toQString(this->hasCustomUserAgent); + details[ConfProperties::ALLOW_CERT_FROM_HISTORY] = toQString(this->allowIncoming); + details[ConfProperties::ALLOW_CERT_FROM_CONTACT] = toQString(this->allowIncoming); + details[ConfProperties::ALLOW_CERT_FROM_TRUSTED] = toQString(this->allowIncoming); + details[ConfProperties::ACCOUNT_IP_AUTO_REWRITE] = toQString(this->allowIPAutoRewrite); + details[ConfProperties::ARCHIVE_PASSWORD] = this->archivePassword; + details[ConfProperties::ARCHIVE_HAS_PASSWORD] = toQString(this->archiveHasPassword); + details[ConfProperties::ARCHIVE_PATH] = this->archivePath; + details[ConfProperties::ARCHIVE_PIN] = this->archivePin; + // ConfProperties::DEVICE_NAME name is set with NewDeviceModel interface + details[ConfProperties::PROXY_ENABLED] = toQString(this->proxyEnabled); + details[ConfProperties::PROXY_SERVER] = this->proxyServer; + details[ConfProperties::PROXY_PUSH_TOKEN] = this->proxyPushToken; + details[ConfProperties::DHT_PEER_DISCOVERY] = toQString(this->peerDiscovery); + details[ConfProperties::ACCOUNT_PEER_DISCOVERY] = toQString(this->accountDiscovery); + details[ConfProperties::ACCOUNT_PUBLISH] = toQString(this->accountPublish); + details[ConfProperties::KEEP_ALIVE_ENABLED] = toQString(this->keepAliveEnabled); + details[ConfProperties::BOOTSTRAP_LIST_URL] = this->bootstrapListUrl; + details[ConfProperties::DHT_PROXY_LIST_URL] = this->dhtProxyListUrl; + details[ConfProperties::DEFAULT_MODERATORS] = this->defaultModerators; + details[ConfProperties::LOCAL_MODERATORS_ENABLED] = toQString(this->localModeratorsEnabled); + // Audio + details[ConfProperties::Audio::PORT_MAX] = toQString(this->Audio.audioPortMax); + details[ConfProperties::Audio::PORT_MIN] = toQString(this->Audio.audioPortMin); + // Video + details[ConfProperties::Video::ENABLED] = toQString(this->Video.videoEnabled); + details[ConfProperties::Video::PORT_MAX] = toQString(this->Video.videoPortMax); + details[ConfProperties::Video::PORT_MIN] = toQString(this->Video.videoPortMin); + // STUN + details[ConfProperties::STUN::SERVER] = this->STUN.server; + details[ConfProperties::STUN::ENABLED] = toQString(this->STUN.enable); + // TURN + details[ConfProperties::TURN::SERVER] = this->TURN.server; + details[ConfProperties::TURN::ENABLED] = toQString(this->TURN.enable); + details[ConfProperties::TURN::SERVER_UNAME] = this->TURN.username; + details[ConfProperties::TURN::SERVER_PWD] = this->TURN.password; + details[ConfProperties::TURN::SERVER_REALM] = this->TURN.realm; + // Presence + details[ConfProperties::Presence::SUPPORT_PUBLISH] = toQString( + this->Presence.presencePublishSupported); + details[ConfProperties::Presence::SUPPORT_SUBSCRIBE] = toQString( + this->Presence.presenceSubscribeSupported); + details[ConfProperties::Presence::ENABLED] = toQString(this->Presence.presenceEnabled); + // Ringtone + details[ConfProperties::Ringtone::PATH] = this->Ringtone.ringtonePath; + details[ConfProperties::Ringtone::ENABLED] = toQString(this->Ringtone.ringtoneEnabled); + // SRTP + details[ConfProperties::SRTP::KEY_EXCHANGE] = this->SRTP.keyExchange + == account::KeyExchangeProtocol::NONE + ? "" + : "sdes"; + details[ConfProperties::SRTP::ENABLED] = toQString(this->SRTP.enable); + details[ConfProperties::SRTP::RTP_FALLBACK] = toQString(this->SRTP.rtpFallback); + // TLS + details[ConfProperties::TLS::LISTENER_PORT] = toQString(this->TLS.listenerPort); + details[ConfProperties::TLS::ENABLED] = toQString(this->TLS.enable); + details[ConfProperties::TLS::PORT] = toQString(this->TLS.port); + details[ConfProperties::TLS::CA_LIST_FILE] = this->TLS.certificateListFile; + details[ConfProperties::TLS::CERTIFICATE_FILE] = this->TLS.certificateFile; + details[ConfProperties::TLS::PRIVATE_KEY_FILE] = this->TLS.privateKeyFile; + details[ConfProperties::TLS::PASSWORD] = this->TLS.password; + switch (this->TLS.method) { + case account::TlsMethod::TLSv1: + details[ConfProperties::TLS::METHOD] = "TLSv1"; + break; + case account::TlsMethod::TLSv1_1: + details[ConfProperties::TLS::METHOD] = "TLSv1.1"; + break; + case account::TlsMethod::TLSv1_2: + details[ConfProperties::TLS::METHOD] = "TLSv1.2"; + break; + case account::TlsMethod::DEFAULT: + default: + details[ConfProperties::TLS::METHOD] = "Default"; + break; + } + details[ConfProperties::TLS::CIPHERS] = this->TLS.ciphers; + details[ConfProperties::TLS::SERVER_NAME] = this->TLS.serverName; + details[ConfProperties::TLS::VERIFY_SERVER] = toQString(this->TLS.verifyServer); + details[ConfProperties::TLS::VERIFY_CLIENT] = toQString(this->TLS.verifyClient); + details[ConfProperties::TLS::REQUIRE_CLIENT_CERTIFICATE] = toQString( + this->TLS.requireClientCertificate); + details[ConfProperties::TLS::NEGOTIATION_TIMEOUT_SEC] = toQString( + this->TLS.negotiationTimeoutSec); + // DHT + details[ConfProperties::DHT::PORT] = toQString(this->DHT.port); + details[ConfProperties::DHT::PUBLIC_IN_CALLS] = toQString(this->DHT.PublicInCalls); + details[ConfProperties::DHT::ALLOW_FROM_TRUSTED] = toQString(this->DHT.AllowFromTrusted); + // RingNS + details[ConfProperties::RingNS::URI] = this->RingNS.uri; + details[ConfProperties::RingNS::ACCOUNT] = this->RingNS.account; + // Registration + details[ConfProperties::Registration::EXPIRE] = toQString(this->Registration.expire); + // Manager + details[ConfProperties::MANAGER_URI] = this->managerUri; + details[ConfProperties::MANAGER_USERNAME] = this->managerUsername; + + return details; +} + +QString +NewAccountModel::createNewAccount(profile::Type type, + const QString& displayName, + const QString& archivePath, + const QString& password, + const QString& pin, + const QString& uri, + const MapStringString& config) +{ + MapStringString details = type == profile::Type::SIP + ? ConfigurationManager::instance().getAccountTemplate("SIP") + : ConfigurationManager::instance().getAccountTemplate("RING"); + using namespace DRing::Account; + details[ConfProperties::TYPE] = type == profile::Type::SIP ? "SIP" : "RING"; + details[ConfProperties::DISPLAYNAME] = displayName; + details[ConfProperties::ALIAS] = displayName; + details[ConfProperties::UPNP_ENABLED] = "true"; + details[ConfProperties::ARCHIVE_PASSWORD] = password; + details[ConfProperties::ARCHIVE_PIN] = pin; + details[ConfProperties::ARCHIVE_PATH] = archivePath; + if (type == profile::Type::SIP) + details[ConfProperties::USERNAME] = uri; + if (!config.isEmpty()) { + for (MapStringString::const_iterator it = config.begin(); it != config.end(); it++) { + details[it.key()] = it.value(); + } + } + + QString accountId = ConfigurationManager::instance().addAccount(details); + return accountId; +} + +QString +NewAccountModel::connectToAccountManager(const QString& username, + const QString& password, + const QString& serverUri, + const MapStringString& config) +{ + MapStringString details = ConfigurationManager::instance().getAccountTemplate("RING"); + using namespace DRing::Account; + details[ConfProperties::TYPE] = "RING"; + details[ConfProperties::MANAGER_URI] = serverUri; + details[ConfProperties::MANAGER_USERNAME] = username; + details[ConfProperties::ARCHIVE_PASSWORD] = password; + if (!config.isEmpty()) { + for (MapStringString::const_iterator it = config.begin(); it != config.end(); it++) { + details[it.key()] = it.value(); + } + } + + QString accountId = ConfigurationManager::instance().addAccount(details); + return accountId; +} + +void +NewAccountModel::setTopAccount(const QString& accountId) +{ + bool found = false; + QString order = {}; + + const QStringList accountIds = ConfigurationManager::instance().getAccountList(); + for (auto& id : accountIds) { + if (id == accountId) { + found = true; + } else { + order += id + "/"; + } + } + if (found) { + order = accountId + "/" + order; + } + ConfigurationManager::instance().setAccountsOrder(order); +} + +QString +NewAccountModel::accountVCard(const QString& accountId, bool compressImage) const +{ + return authority::storage::vcard::profileToVcard(getAccountInfo(accountId).profileInfo, + compressImage); +} + +const QString +NewAccountModel::bestNameForAccount(const QString& accountID) +{ + // Order: Alias, registeredName, uri + auto& accountInfo = getAccountInfo(accountID); + + auto alias = accountInfo.profileInfo.alias.simplified(); + auto registeredName = accountInfo.registeredName.simplified(); + auto infoHash = accountInfo.profileInfo.uri.simplified(); + + if (alias.isEmpty()) { + if (registeredName.isEmpty()) + return infoHash; + else + return registeredName; + } + return alias; +} + +const QString +NewAccountModel::bestIdForAccount(const QString& accountID) +{ + // Order: RegisteredName, uri after best name + // return empty string if duplicated with best name + auto& accountInfo = getAccountInfo(accountID); + + auto registeredName = accountInfo.registeredName.simplified(); + auto infoHash = accountInfo.profileInfo.uri.simplified(); + + return registeredName.isEmpty() ? infoHash : registeredName; +} + +void +NewAccountModel::setDefaultModerator(const QString& accountID, + const QString& peerURI, + const bool& state) +{ + ConfigurationManager::instance().setDefaultModerator(accountID, peerURI, state); +} + +QStringList +NewAccountModel::getDefaultModerators(const QString& accountID) +{ + return ConfigurationManager::instance().getDefaultModerators(accountID); +} + +void +NewAccountModel::enableLocalModerators(const QString& accountID, const bool& isModEnabled) +{ + ConfigurationManager::instance().enableLocalModerators(accountID, isModEnabled); +} + +bool +NewAccountModel::isLocalModeratorsEnabled(const QString& accountID) +{ + return ConfigurationManager::instance().isLocalModeratorsEnabled(accountID); +} + +void +NewAccountModel::setAllModerators(const QString& accountID, const bool& allModerators) +{ + ConfigurationManager::instance().setAllModerators(accountID, allModerators); +} + +bool +NewAccountModel::isAllModerators(const QString& accountID) +{ + return ConfigurationManager::instance().isAllModerators(accountID); +} + +int +NewAccountModel::notificationsCount() const +{ + auto total = 0; + for (const auto& [_id, account] : pimpl_->accounts) { + total += account.first.conversationModel->notificationsCount(); + } + return total; +} + +QString +NewAccountModel::avatar(const QString& accountId) const +{ + return authority::storage::avatar(accountId); +} + + +} // namespace lrc + +#include "api/moc_newaccountmodel.cpp" +#include "newaccountmodel.moc" diff --git a/src/libclient/newcallmodel.cpp b/src/libclient/newcallmodel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5fbcc9b2f6e8406cc1a191184ae59b5555fcbc03 --- /dev/null +++ b/src/libclient/newcallmodel.cpp @@ -0,0 +1,1642 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author : Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * + * Author : Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include "api/newcallmodel.h" + +// Lrc +#include "callbackshandler.h" +#include "api/avmodel.h" +#include "api/behaviorcontroller.h" +#include "api/conversationmodel.h" +#include "api/contact.h" +#include "api/contactmodel.h" +#include "api/pluginmodel.h" +#include "api/callparticipantsmodel.h" +#include "api/lrc.h" +#include "api/newaccountmodel.h" +#include "authority/storagehelper.h" +#include "dbus/callmanager.h" +#include "dbus/videomanager.h" +#include "vcard.h" +#include "renderer.h" +#include "typedefs.h" +#include "uri.h" + +// Ring daemon +#include <media_const.h> +#include <account_const.h> + +// Qt +#include <QObject> +#include <QString> +#include <QUrl> +#include <QSize> + +// std +#include <chrono> +#include <random> +#include <map> + +using namespace DRing::Media; + +static std::uniform_int_distribution<int> dis {0, std::numeric_limits<int>::max()}; +static const std::map<short, QString> + sip_call_status_code_map {{0, QObject::tr("Null")}, + {100, QObject::tr("Trying")}, + {180, QObject::tr("Ringing")}, + {181, QObject::tr("Being Forwarded")}, + {182, QObject::tr("Queued")}, + {183, QObject::tr("Progress")}, + {200, QObject::tr("OK")}, + {202, QObject::tr("Accepted")}, + {300, QObject::tr("Multiple Choices")}, + {301, QObject::tr("Moved Permanently")}, + {302, QObject::tr("Moved Temporarily")}, + {305, QObject::tr("Use Proxy")}, + {380, QObject::tr("Alternative Service")}, + {400, QObject::tr("Bad Request")}, + {401, QObject::tr("Unauthorized")}, + {402, QObject::tr("Payment Required")}, + {403, QObject::tr("Forbidden")}, + {404, QObject::tr("Not Found")}, + {405, QObject::tr("Method Not Allowed")}, + {406, QObject::tr("Not Acceptable")}, + {407, QObject::tr("Proxy Authentication Required")}, + {408, QObject::tr("Request Timeout")}, + {410, QObject::tr("Gone")}, + {413, QObject::tr("Request Entity Too Large")}, + {414, QObject::tr("Request URI Too Long")}, + {415, QObject::tr("Unsupported Media Type")}, + {416, QObject::tr("Unsupported URI Scheme")}, + {420, QObject::tr("Bad Extension")}, + {421, QObject::tr("Extension Required")}, + {422, QObject::tr("Session Timer Too Small")}, + {423, QObject::tr("Interval Too Brief")}, + {480, QObject::tr("Temporarily Unavailable")}, + {481, QObject::tr("Call TSX Does Not Exist")}, + {482, QObject::tr("Loop Detected")}, + {483, QObject::tr("Too Many Hops")}, + {484, QObject::tr("Address Incomplete")}, + {485, QObject::tr("Ambiguous")}, + {486, QObject::tr("Busy")}, + {487, QObject::tr("Request Terminated")}, + {488, QObject::tr("Not Acceptable")}, + {489, QObject::tr("Bad Event")}, + {490, QObject::tr("Request Updated")}, + {491, QObject::tr("Request Pending")}, + {493, QObject::tr("Undecipherable")}, + {500, QObject::tr("Internal Server Error")}, + {501, QObject::tr("Not Implemented")}, + {502, QObject::tr("Bad Gateway")}, + {503, QObject::tr("Service Unavailable")}, + {504, QObject::tr("Server Timeout")}, + {505, QObject::tr("Version Not Supported")}, + {513, QObject::tr("Message Too Large")}, + {580, QObject::tr("Precondition Failure")}, + {600, QObject::tr("Busy Everywhere")}, + {603, QObject::tr("Call Refused")}, + {604, QObject::tr("Does Not Exist Anywhere")}, + {606, QObject::tr("Not Acceptable Anywhere")}}; + +namespace lrc { + +using namespace api; + +class NewCallModelPimpl : public QObject +{ + Q_OBJECT +public: + NewCallModelPimpl(const NewCallModel& linked, + Lrc& lrc, + const CallbacksHandler& callbacksHandler, + const BehaviorController& behaviorController); + ~NewCallModelPimpl(); + + /** + * Send the profile VCard into a call + * @param callId + */ + void sendProfile(const QString& callId); + + NewCallModel::CallInfoMap calls; + NewCallModel::CallParticipantsModelMap participantsModel; + const CallbacksHandler& callbacksHandler; + const NewCallModel& linked; + const BehaviorController& behaviorController; + + /** + * key = peer's uri + * vector = chunks + * @note chunks are counted from 1 to number of parts. We use 0 to store the actual number of + * parts stored + */ + std::map<QString, VectorString> vcardsChunks; + + /** + * Retrieve active calls from the daemon and init the model + */ + void initCallFromDaemon(); + + /** + * Retrieve active conferences from the daemon and init the model + */ + void initConferencesFromDaemon(); + + /** + * Check if media device is muted + */ + bool checkMediaDeviceMuted(const MapStringString& mediaAttributes); + + bool manageCurrentCall_ {true}; + QString currentCall_ {}; + + Lrc& lrc; + + QList<call::PendingConferenceeInfo> pendingConferencees_; + +public Q_SLOTS: + /** + * Listen from CallbacksHandler when a call is incoming + * @param accountId account which receives the call + * @param callId + * @param fromId peer uri + * @param displayname + * @param mediaList media received + */ + void slotIncomingCallWithMedia(const QString& accountId, + const QString& callId, + const QString& fromId, + const QString& displayname, + const VectorMapStringString& mediaList); + /** + * Connect this signal to know when a call arrives + * @param accountId the one who receives the call + * @param callId the call id + * @param mediaList new media received + */ + void slotMediaChangeRequested(const QString& accountId, + const QString& callId, + const VectorMapStringString& mediaList); + /** + * Listen from CallbacksHandler when a call got a new state + * @param accountId + * @param callId + * @param state the new state + * @param code unused + */ + void slotCallStateChanged(const QString& accountId, + const QString& callId, + const QString& state, + int code); + /** + * Listen from CallbacksHandler when a call medias are ready + * @param callId + * @param event + * @param mediaList + */ + void slotMediaNegotiationStatus(const QString& callId, + const QString& event, + const VectorMapStringString& mediaList); + /** + * Listen from CallbacksHandler when a VCard chunk is incoming + * @param accountId + * @param callId + * @param from + * @param part + * @param numberOfParts + * @param payload + */ + void slotincomingVCardChunk(const QString& accountId, + const QString& callId, + const QString& from, + int part, + int numberOfParts, + const QString& payload); + /** + * Listen from CallbacksHandler when a conference is created. + * @param callId + */ + void slotConferenceCreated(const QString& accountId, const QString& callId); + /** + * Listen from CallbacksHandler when a voice mail notice is incoming + * @param accountId + * @param newCount + * @param oldCount + * @param urgentCount + */ + void slotVoiceMailNotify(const QString& accountId, int newCount, int oldCount, int urgentCount); + /** + * Listen from CallManager when a conference layout is updated + * @param confId + * @param infos + */ + void slotOnConferenceInfosUpdated(const QString& confId, const VectorMapStringString& infos); + /** + * Listen from CallbacksHandler when the peer start recording + * @param callId + * @param state the new state + */ + void remoteRecordingChanged(const QString& callId, const QString& peerNumber, bool state); + /** + * Listen from CallbacksHandler when a renderer starts + * @param id + * @param shmPath + * @param width + * @param height + */ + void onDecodingStarted(const QString& id, const QString& shmPath, int width, int height); +}; + +NewCallModel::NewCallModel(const account::Info& owner, + Lrc& lrc, + const CallbacksHandler& callbacksHandler, + const BehaviorController& behaviorController) + : QObject(nullptr) + , owner(owner) + , pimpl_(std::make_unique<NewCallModelPimpl>(*this, lrc, callbacksHandler, behaviorController)) +{} + +NewCallModel::~NewCallModel() {} + +const call::Info& +NewCallModel::getCallFromURI(const QString& uri, bool notOver) const +{ + // For a NON SIP account the scheme can be ring:. Sometimes it can miss, and will be certainly + // replaced by jami://. + // Just make the comparaison ignoring the scheme and check the rest. + auto uriObj = URI(uri); + for (const auto& call : pimpl_->calls) { + auto contactUri = URI(call.second->peerUri); + if (uriObj.userinfo() == contactUri.userinfo() + and uriObj.hostname() == contactUri.hostname()) { + if (!notOver || !call::isTerminating(call.second->status)) + return *call.second; + } + } + throw std::out_of_range("No call at URI " + uri.toStdString()); +} + +const call::Info& +NewCallModel::getConferenceFromURI(const QString& uri) const +{ + for (const auto& call : pimpl_->calls) { + if (call.second->type == call::Type::CONFERENCE) { + QStringList callList = CallManager::instance().getParticipantList(owner.id, call.first); + Q_FOREACH (const auto& callId, callList) { + try { + if (pimpl_->calls.find(callId) != pimpl_->calls.end() + && pimpl_->calls[callId]->peerUri == uri) { + return *call.second; + } + } catch (...) { + } + } + } + } + throw std::out_of_range("No call at URI " + uri.toStdString()); +} + +VectorString +NewCallModel::getConferenceSubcalls(const QString& confId) +{ + QStringList callList = CallManager::instance().getParticipantList(owner.id, confId); + VectorString result; + result.reserve(callList.size()); + Q_FOREACH (const auto& callId, callList) { + result.push_back(callId); + } + return result; +} + +const call::Info& +NewCallModel::getCall(const QString& uid) const +{ + return *pimpl_->calls.at(uid); +} + +const CallParticipants& +NewCallModel::getParticipantsInfos(const QString& callId) +{ + if (pimpl_->participantsModel.find(callId) == pimpl_->participantsModel.end()) { + VectorMapStringString infos = {}; + pimpl_->participantsModel + .emplace(callId, std::make_shared<CallParticipants>(infos, callId, pimpl_->linked)); + } + return *pimpl_->participantsModel.at(callId); +} + +void +NewCallModel::updateCallMediaList(const QString& callId, bool acceptVideo) +{ + try { + auto callInfos = pimpl_->calls.find(callId); + if (callInfos != pimpl_->calls.end()) { + for (auto it = callInfos->second->mediaList.begin(); + it != callInfos->second->mediaList.end(); + it++) { + if ((*it)[MediaAttributeKey::MEDIA_TYPE] == MediaAttributeValue::VIDEO + && !acceptVideo) { + (*it)[MediaAttributeKey::ENABLED] = "false"; + (*it)[MediaAttributeKey::MUTED] = "true"; + callInfos->second->videoMuted = !acceptVideo; + } + } + } + } catch (...) { + } +} + +QString +NewCallModel::createCall(const QString& uri, bool isAudioOnly, VectorMapStringString mediaList) +{ + if (mediaList.isEmpty()) { + MapStringString mediaAttribute = {{MediaAttributeKey::MEDIA_TYPE, + MediaAttributeValue::AUDIO}, + {MediaAttributeKey::ENABLED, "true"}, + {MediaAttributeKey::MUTED, "false"}, + {MediaAttributeKey::SOURCE, ""}, + {MediaAttributeKey::LABEL, "audio_0"}}; + mediaList.push_back(mediaAttribute); + if (!isAudioOnly) { + mediaAttribute[MediaAttributeKey::MEDIA_TYPE] = MediaAttributeValue::VIDEO; + mediaAttribute[MediaAttributeKey::LABEL] = "video_0"; + mediaList.push_back(mediaAttribute); + } + } +#ifdef ENABLE_LIBWRAP + auto callId = CallManager::instance().placeCallWithMedia(owner.id, uri, mediaList); +#else // dbus + // do not use auto here (QDBusPendingReply<QString>) + QString callId = CallManager::instance().placeCallWithMedia(owner.id, uri, mediaList); +#endif // ENABLE_LIBWRAP + + if (callId.isEmpty()) { + qDebug() << "no call placed between (account: " << owner.id << ", contact: " << uri << ")"; + return ""; + } + + auto callInfo = std::make_shared<call::Info>(); + callInfo->id = callId; + callInfo->peerUri = uri; + callInfo->isOutgoing = true; + callInfo->status = call::Status::SEARCHING; + callInfo->type = call::Type::DIALOG; + callInfo->isAudioOnly = isAudioOnly; + callInfo->videoMuted = isAudioOnly; + callInfo->mediaList = mediaList; + pimpl_->calls.emplace(callId, std::move(callInfo)); + + return callId; +} + +void +NewCallModel::requestMediaChange(const QString& callId, + const QString& mediaLabel, + const QString& uri, + MediaRequestType type, + bool mute) +{ + // Main audio: audio_0 + // Main video: video_0 + + auto& callInfo = pimpl_->calls[callId]; + if (!callInfo) + return; + + QString sep = DRing::Media::VideoProtocolPrefix::SEPARATOR; + // The media label must contain either "audio" or "video" substring, + // otherwise the media will be considered as of un-supported type. + QString mediaType = mediaLabel.contains("audio") + ? MediaAttributeValue::AUDIO + : (mediaLabel.contains("video") ? MediaAttributeValue::VIDEO : ""); + + if (mediaType.isEmpty()) { + qCritical() << "No valide media type found in media label!"; + return; + } + + QString resource {}; + QString srctype {}; + auto proposedList = callInfo->mediaList; + + int found = 0; + + switch (type) { + case MediaRequestType::FILESHARING: { + // File sharing + resource = !uri.isEmpty() ? QString("%1%2%3") + .arg(DRing::Media::VideoProtocolPrefix::FILE) + .arg(sep) + .arg(QUrl(uri).toLocalFile()) + : DRing::Media::VideoProtocolPrefix::NONE; + if (not resource.isEmpty()) + srctype = MediaAttributeValue::SRC_TYPE_FILE; + break; + } + case MediaRequestType::SCREENSHARING: { + // Screen/window sharing + resource = uri; + srctype = MediaAttributeValue::SRC_TYPE_DISPLAY; + break; + } + case MediaRequestType::CAMERA: { + // Camera device + if (mediaLabel.contains("video")) { + resource = not uri.isEmpty() ? QString("%1%2%3") + .arg(DRing::Media::VideoProtocolPrefix::CAMERA) + .arg(sep) + .arg(uri) + : DRing::Media::VideoProtocolPrefix::NONE; + } + srctype = MediaAttributeValue::SRC_TYPE_CAPTURE_DEVICE; + break; + } + default: + return; + } + + if (callInfo->type == call::Type::CONFERENCE) { + MapStringString mediaAttribute = {{MediaAttributeKey::MEDIA_TYPE, mediaType}, + {MediaAttributeKey::ENABLED, "true"}, + {MediaAttributeKey::MUTED, mute ? "true" : "false"}, + {MediaAttributeKey::SOURCE_TYPE, srctype}, + {MediaAttributeKey::SOURCE, resource}, + {MediaAttributeKey::LABEL, mediaLabel}}; + proposedList.push_back(mediaAttribute); + } + + for (auto& item : proposedList) { + if (item[MediaAttributeKey::LABEL] == mediaLabel) { + mute = resource.isEmpty() ? item[MediaAttributeKey::MUTED] == "false" : mute; + item[MediaAttributeKey::ENABLED] = "true"; + item[MediaAttributeKey::MUTED] = mute ? "true" : "false"; + item[MediaAttributeKey::SOURCE_TYPE] = srctype; + // For now, only the video source can be changed by the client. + if (item[MediaAttributeKey::MEDIA_TYPE] == MediaAttributeValue::VIDEO) { + item[MediaAttributeKey::SOURCE] = resource.isEmpty() + ? item[MediaAttributeKey::SOURCE] + : resource; + } + break; + } + found++; + } + + if (found == proposedList.size() && mediaLabel == "video_0") { + mute &= !resource.isEmpty(); + MapStringString mediaAttribute = {{MediaAttributeKey::MEDIA_TYPE, + MediaAttributeValue::VIDEO}, + {MediaAttributeKey::ENABLED, "true"}, + {MediaAttributeKey::MUTED, mute ? "true" : "false"}, + {MediaAttributeKey::SOURCE_TYPE, srctype}, + {MediaAttributeKey::SOURCE, resource}, + {MediaAttributeKey::LABEL, mediaLabel}}; + proposedList.push_back(mediaAttribute); + } + + CallManager::instance().requestMediaChange(owner.id, callId, proposedList); + + // If media existed and its mute state was changed here, then we should + // update the mediaList because we will not receive signal + // mediaNegotiationStatus + if (found < callInfo->mediaList.size()) { + callInfo->mediaList = proposedList; + if (mediaLabel.contains("audio_0")) { + callInfo->audioMuted = mute; + } else if (mediaLabel.contains("video_0")) { + callInfo->videoMuted = mute; + } + if (callInfo->status == call::Status::IN_PROGRESS) + Q_EMIT callInfosChanged(owner.id, callId); + } +} + +void +NewCallModel::accept(const QString& callId) const +{ + try { + auto& callInfo = pimpl_->calls[callId]; + if (!callInfo) + return; + if (callInfo->mediaList.empty()) + CallManager::instance().accept(owner.id, callId); + else + CallManager::instance().acceptWithMedia(owner.id, callId, callInfo->mediaList); + } catch (...) { + } +} + +void +NewCallModel::hangUp(const QString& callId) const +{ + if (!hasCall(callId)) + return; + auto& call = pimpl_->calls[callId]; + + if (call->status == call::Status::INCOMING_RINGING) { + CallManager::instance().refuse(owner.id, callId); + return; + } + + switch (call->type) { + case call::Type::DIALOG: + CallManager::instance().hangUp(owner.id, callId); + break; + case call::Type::CONFERENCE: + CallManager::instance().hangUpConference(owner.id, callId); + break; + case call::Type::INVALID: + default: + break; + } +} + +void +NewCallModel::refuse(const QString& callId) const +{ + if (!hasCall(callId)) + return; + CallManager::instance().refuse(owner.id, callId); +} + +void +NewCallModel::toggleAudioRecord(const QString& callId) const +{ + CallManager::instance().toggleRecording(owner.id, callId); +} + +void +NewCallModel::playDTMF(const QString& callId, const QString& value) const +{ + if (!hasCall(callId)) + return; + if (pimpl_->calls[callId]->status != call::Status::IN_PROGRESS) + return; + CallManager::instance().playDTMF(value); +} + +void +NewCallModel::togglePause(const QString& callId) const +{ + // function should now only serves for SIP accounts + if (!hasCall(callId)) + return; + auto& call = pimpl_->calls[callId]; + + if (call->status == call::Status::PAUSED) { + if (call->type == call::Type::DIALOG) { + CallManager::instance().unhold(owner.id, callId); + } else { + CallManager::instance().unholdConference(owner.id, callId); + } + } else if (call->status == call::Status::IN_PROGRESS) { + if (call->type == call::Type::DIALOG) + CallManager::instance().hold(owner.id, callId); + else { + CallManager::instance().holdConference(owner.id, callId); + } + } +} + +void +NewCallModel::toggleMedia(const QString& callId, const NewCallModel::Media media) +{ + if (!hasCall(callId)) + return; + auto mediaLabel = media == NewCallModel::Media::VIDEO ? "video_0" : "audio_0"; + requestMediaChange(callId, mediaLabel, "", MediaRequestType::CAMERA, true); +} + +void +NewCallModel::setQuality(const QString& callId, const double quality) const +{ + Q_UNUSED(callId) + Q_UNUSED(quality) + qDebug() << "setQuality isn't implemented yet"; +} + +void +NewCallModel::transfer(const QString& callId, const QString& to) const +{ + CallManager::instance().transfer(owner.id, callId, to); +} + +void +NewCallModel::transferToCall(const QString& callId, const QString& callIdDest) const +{ + CallManager::instance().attendedTransfer(owner.id, callId, callIdDest); +} + +void +NewCallModel::joinCalls(const QString& callIdA, const QString& callIdB) const +{ + // Get call informations + call::Info call1, call2; + QString accountIdCall1 = {}, accountIdCall2 = {}; + for (const auto& account_id : owner.accountModel->getAccountList()) { + try { + auto& accountInfo = owner.accountModel->getAccountInfo(account_id); + if (accountInfo.callModel->hasCall(callIdA)) { + call1 = accountInfo.callModel->getCall(callIdA); + accountIdCall1 = account_id; + } + if (accountInfo.callModel->hasCall(callIdB)) { + call2 = accountInfo.callModel->getCall(callIdB); + accountIdCall2 = account_id; + } + if (!accountIdCall1.isEmpty() && !accountIdCall2.isEmpty()) + break; + } catch (...) { + } + } + if (accountIdCall1.isEmpty() || accountIdCall2.isEmpty()) { + qWarning() << "Can't join inexistent calls."; + return; + } + + if (call1.type == call::Type::CONFERENCE && call2.type == call::Type::CONFERENCE) { + bool joined = CallManager::instance().joinConference(accountIdCall1, + callIdA, + accountIdCall2, + callIdB); + + if (!joined) { + qWarning() << "Conference: " << callIdA << " couldn't join conference " << callIdB; + return; + } + if (accountIdCall1 != owner.id) { + // If the conference is added from another account + try { + auto& accountInfo = owner.accountModel->getAccountInfo(accountIdCall1); + if (accountInfo.callModel->hasCall(callIdA)) { + Q_EMIT accountInfo.callModel->callAddedToConference(callIdA, callIdB); + } + } catch (...) { + } + } else { + Q_EMIT callAddedToConference(callIdA, callIdB); + } + } else if (call1.type == call::Type::CONFERENCE || call2.type == call::Type::CONFERENCE) { + auto call = call1.type == call::Type::CONFERENCE ? callIdB : callIdA; + auto conf = call1.type == call::Type::CONFERENCE ? callIdA : callIdB; + // Unpause conference if conference was not active + CallManager::instance().unholdConference(owner.id, conf); + auto accountCall = call1.type == call::Type::CONFERENCE ? accountIdCall2 : accountIdCall1; + + bool joined = CallManager::instance().addParticipant(accountCall, call, accountCall, conf); + if (!joined) { + qWarning() << "Call: " << call << " couldn't join conference " << conf; + return; + } + if (accountCall != owner.id) { + // If the call is added from another account + try { + auto& accountInfo = owner.accountModel->getAccountInfo(accountCall); + if (accountInfo.callModel->hasCall(call)) { + accountInfo.callModel->pimpl_->slotConferenceCreated(owner.id, conf); + } + } catch (...) { + } + } else + Q_EMIT callAddedToConference(call, conf); + + // Remove from pendingConferences_ + for (int i = 0; i < pimpl_->pendingConferencees_.size(); ++i) { + if (pimpl_->pendingConferencees_.at(i).callId == call) { + Q_EMIT beginRemovePendingConferenceesRows(i); + pimpl_->pendingConferencees_.removeAt(i); + Q_EMIT endRemovePendingConferenceesRows(); + break; + } + } + } else { + CallManager::instance().joinParticipant(accountIdCall1, callIdA, accountIdCall2, callIdB); + // NOTE: This will trigger slotConferenceCreated. + } +} + +QString +NewCallModel::callAndAddParticipant(const QString uri, const QString& callId, bool audioOnly) +{ + auto newCallId = createCall(uri, audioOnly, pimpl_->calls[callId]->mediaList); + Q_EMIT beginInsertPendingConferenceesRows(0); + pimpl_->pendingConferencees_.prepend({uri, newCallId, callId}); + Q_EMIT endInsertPendingConferenceesRows(); + return newCallId; +} + +void +NewCallModel::removeParticipant(const QString& callId, const QString& participant) const +{ + Q_UNUSED(callId) + Q_UNUSED(participant) + qDebug() << "removeParticipant() isn't implemented yet"; +} + +QString +NewCallModel::getFormattedCallDuration(const QString& callId) const +{ + if (!hasCall(callId)) + return "00:00"; + auto& startTime = pimpl_->calls[callId]->startTime; + if (startTime.time_since_epoch().count() == 0) + return "00:00"; + auto now = std::chrono::steady_clock::now(); + auto d = std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch() + - startTime.time_since_epoch()) + .count(); + return authority::storage::getFormattedCallDuration(d); +} + +bool +NewCallModel::isRecording(const QString& callId) const +{ + if (!hasCall(callId)) + return false; + return CallManager::instance().getIsRecording(owner.id, callId); +} + +QString +NewCallModel::getSIPCallStatusString(const short& statusCode) +{ + auto element = sip_call_status_code_map.find(statusCode); + if (element != sip_call_status_code_map.end()) { + return element->second; + } + return ""; +} + +const QList<call::PendingConferenceeInfo>& +NewCallModel::getPendingConferencees() +{ + return pimpl_->pendingConferencees_; +} + +api::video::RenderedDevice +NewCallModel::getCurrentRenderedDevice(const QString& call_id) const +{ + video::RenderedDevice result; + MapStringString callDetails; + QStringList conferences = CallManager::instance().getConferenceList(owner.id); + if (conferences.indexOf(call_id) != -1) { + callDetails = CallManager::instance().getConferenceDetails(owner.id, call_id); + } else { + callDetails = CallManager::instance().getCallDetails(owner.id, call_id); + } + if (!callDetails.contains("VIDEO_SOURCE")) { + return result; + } + auto source = callDetails["VIDEO_SOURCE"]; + auto sourceSize = source.size(); + if (source.startsWith("camera://")) { + result.type = video::DeviceType::CAMERA; + result.name = source.right(sourceSize - QString("camera://").size()); + } else if (source.startsWith("file://")) { + result.type = video::DeviceType::FILE; + result.name = source.right(sourceSize - QString("file://").size()); + } else if (source.startsWith("display://")) { + result.type = video::DeviceType::DISPLAY; + result.name = source.right(sourceSize - QString("display://").size()); + } + return result; +} + +void +NewCallModel::setInputFile(const QString& uri, const QString& callId) +{ + QString sep = DRing::Media::VideoProtocolPrefix::SEPARATOR; + auto resource = !uri.isEmpty() ? QString("%1%2%3") + .arg(DRing::Media::VideoProtocolPrefix::FILE) + .arg(sep) + .arg(QUrl(uri).toLocalFile()) + : DRing::Media::VideoProtocolPrefix::NONE; + if (callId.isEmpty()) { + VideoManager::instance().openVideoInput(resource); + } else { + CallManager::instance().switchInput(owner.id, callId, resource); + } +} + +QString +NewCallModel::getDisplay(int idx, int x, int y, int w, int h) +{ + QString sep = DRing::Media::VideoProtocolPrefix::SEPARATOR; + return QString("%1%2:%3+%4,%5 %6x%7") + .arg(DRing::Media::VideoProtocolPrefix::DISPLAY) + .arg(sep) + .arg(idx) + .arg(x) + .arg(y) + .arg(w) + .arg(h); +} + +QString +NewCallModel::getDisplay(const QString& windowId) +{ + QString sep = DRing::Media::VideoProtocolPrefix::SEPARATOR; + return QString("%1%2:+0,0 window-id:%3") + .arg(DRing::Media::VideoProtocolPrefix::DISPLAY) + .arg(sep) + .arg(windowId); +} + +void +NewCallModel::setDisplay(int idx, int x, int y, int w, int h, const QString& callId) +{ + auto resource = getDisplay(idx, x, y, w, h); + if (callId.isEmpty()) { + VideoManager::instance().openVideoInput(resource); + } else { + CallManager::instance().switchInput(owner.id, callId, resource); + } +} + +void +NewCallModel::switchInputTo(const QString& id, const QString& callId) +{ + QString resource; + auto devices = pimpl_->lrc.getAVModel().getDevices(); + auto deviceAvailable = std::find(std::begin(devices), std::end(devices), id); + if (deviceAvailable != devices.end()) { + QString sep = DRing::Media::VideoProtocolPrefix::SEPARATOR; + resource = QString("%1%2%3").arg(DRing::Media::VideoProtocolPrefix::CAMERA).arg(sep).arg(id); + } else { + resource = QString(DRing::Media::VideoProtocolPrefix::NONE); + } + if (callId.isEmpty()) { + VideoManager::instance().openVideoInput(resource); + } else { + CallManager::instance().switchInput(owner.id, callId, resource); + } +} + +NewCallModelPimpl::NewCallModelPimpl(const NewCallModel& linked, + Lrc& lrc, + const CallbacksHandler& callbacksHandler, + const BehaviorController& behaviorController) + : linked(linked) + , lrc(lrc) + , callbacksHandler(callbacksHandler) + , behaviorController(behaviorController) +{ + connect(&callbacksHandler, + &CallbacksHandler::incomingCallWithMedia, + this, + &NewCallModelPimpl::slotIncomingCallWithMedia); + connect(&callbacksHandler, + &CallbacksHandler::mediaChangeRequested, + this, + &NewCallModelPimpl::slotMediaChangeRequested); + connect(&callbacksHandler, + &CallbacksHandler::callStateChanged, + this, + &NewCallModelPimpl::slotCallStateChanged); + connect(&callbacksHandler, + &CallbacksHandler::mediaNegotiationStatus, + this, + &NewCallModelPimpl::slotMediaNegotiationStatus); + connect(&callbacksHandler, + &CallbacksHandler::incomingVCardChunk, + this, + &NewCallModelPimpl::slotincomingVCardChunk); + connect(&callbacksHandler, + &CallbacksHandler::conferenceCreated, + this, + &NewCallModelPimpl::slotConferenceCreated); + connect(&callbacksHandler, + &CallbacksHandler::voiceMailNotify, + this, + &NewCallModelPimpl::slotVoiceMailNotify); + connect(&CallManager::instance(), + &CallManagerInterface::onConferenceInfosUpdated, + this, + &NewCallModelPimpl::slotOnConferenceInfosUpdated); + connect(&callbacksHandler, + &CallbacksHandler::remoteRecordingChanged, + this, + &NewCallModelPimpl::remoteRecordingChanged); + connect(&callbacksHandler, + &CallbacksHandler::decodingStarted, + this, + &NewCallModelPimpl::onDecodingStarted); + +#ifndef ENABLE_LIBWRAP + // Only necessary with dbus since the daemon runs separately + initCallFromDaemon(); + initConferencesFromDaemon(); +#endif +} + +NewCallModelPimpl::~NewCallModelPimpl() {} + +void +NewCallModelPimpl::initCallFromDaemon() +{ + QStringList callList = CallManager::instance().getCallList(linked.owner.id); + for (const auto& callId : callList) { + MapStringString details = CallManager::instance().getCallDetails(linked.owner.id, callId); + auto callInfo = std::make_shared<call::Info>(); + callInfo->id = callId; + auto now = std::chrono::steady_clock::now(); + auto system_now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); + auto diff = static_cast<int64_t>(system_now) + - std::stol(details["TIMESTAMP_START"].toStdString()); + callInfo->startTime = now - std::chrono::seconds(diff); + callInfo->status = call::to_status(details["CALL_STATE"]); + auto endId = details["PEER_NUMBER"].indexOf("@"); + callInfo->peerUri = details["PEER_NUMBER"].left(endId); + if (linked.owner.profileInfo.type == lrc::api::profile::Type::JAMI) { + callInfo->peerUri = "ring:" + callInfo->peerUri; + } + callInfo->videoMuted = details["VIDEO_MUTED"] == "true"; + callInfo->audioMuted = details["AUDIO_MUTED"] == "true"; + callInfo->type = call::Type::DIALOG; + VectorMapStringString infos = CallManager::instance().getConferenceInfos(linked.owner.id, + callId); + auto participantsPtr = std::make_shared<CallParticipants>(infos, callId, linked); + callInfo->layout = participantsPtr->getLayout(); + participantsModel.emplace(callId, std::move(participantsPtr)); + calls.emplace(callId, std::move(callInfo)); + // NOTE/BUG: the videorenderer can't know that the client has restarted + // So, for now, a user will have to manually restart the medias until + // this renderer is not redesigned. + } +} + +bool +NewCallModelPimpl::checkMediaDeviceMuted(const MapStringString& mediaAttributes) +{ + return mediaAttributes[MediaAttributeKey::SOURCE_TYPE] + == MediaAttributeValue::SRC_TYPE_CAPTURE_DEVICE + && (mediaAttributes[MediaAttributeKey::ENABLED] == "false" + || mediaAttributes[MediaAttributeKey::MUTED] == "true"); +} + +void +NewCallModelPimpl::initConferencesFromDaemon() +{ + QStringList callList = CallManager::instance().getConferenceList(linked.owner.id); + for (const auto& callId : callList) { + QMap<QString, QString> details = CallManager::instance() + .getConferenceDetails(linked.owner.id, callId); + auto callInfo = std::make_shared<call::Info>(); + callInfo->id = callId; + QStringList callList = CallManager::instance().getParticipantList(linked.owner.id, callId); + Q_FOREACH (const auto& call, callList) { + MapStringString callDetails = CallManager::instance().getCallDetails(linked.owner.id, + call); + auto now = std::chrono::steady_clock::now(); + auto system_now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); + auto diff = static_cast<int64_t>(system_now) + - std::stol(callDetails["TIMESTAMP_START"].toStdString()); + callInfo->status = details["CONF_STATE"] == "ACTIVE_ATTACHED" + ? call::Status::IN_PROGRESS + : call::Status::PAUSED; + callInfo->startTime = now - std::chrono::seconds(diff); + Q_EMIT linked.callAddedToConference(call, callId); + } + callInfo->type = call::Type::CONFERENCE; + VectorMapStringString infos = CallManager::instance().getConferenceInfos(linked.owner.id, + callId); + auto participantsPtr = std::make_shared<CallParticipants>(infos, callId, linked); + callInfo->layout = participantsPtr->getLayout(); + participantsModel.emplace(callId, std::move(participantsPtr)); + + calls.emplace(callId, std::move(callInfo)); + } +} + +void +NewCallModel::setCurrentCall(const QString& callId) const +{ + if (!pimpl_->manageCurrentCall_) + return; + auto it = std::find_if(pimpl_->pendingConferencees_.begin(), + pimpl_->pendingConferencees_.end(), + [callId](const lrc::api::call::PendingConferenceeInfo& info) -> bool { + return info.callId == callId; + }); + + // Set current call only if not adding this call + // to a current conference + if (it != pimpl_->pendingConferencees_.end()) + return; + if (!hasCall(callId)) + return; + + // The client should be able to set the current call multiple times + if (pimpl_->currentCall_ == callId) + return; + pimpl_->currentCall_ = callId; + + // Unhold call + auto& call = pimpl_->calls[callId]; + if (call->status == call::Status::PAUSED) { + auto& call = pimpl_->calls[callId]; + if (call->type == call::Type::DIALOG) { + CallManager::instance().unhold(owner.id, callId); + } else { + CallManager::instance().unholdConference(owner.id, callId); + } + } + + VectorString filterCalls; + QStringList conferences = CallManager::instance().getConferenceList(owner.id); + for (const auto& confId : conferences) { + QStringList callList = CallManager::instance().getParticipantList(owner.id, confId); + Q_FOREACH (const auto& cid, callList) { + filterCalls.push_back(cid); + } + } + for (const auto& cid : Lrc::activeCalls()) { + auto filtered = std::find(filterCalls.begin(), filterCalls.end(), cid) != filterCalls.end(); + if (cid != callId && !filtered) { + // Only hold calls for a non rendez-vous point + MapStringString callDetails = CallManager::instance().getCallDetails(owner.id, callId); + auto accountId = callDetails["ACCOUNTID"]; + CallManager::instance().hold(owner.id, cid); + } + } + if (!lrc::api::Lrc::holdConferences) { + return; + } + for (const auto& confId : conferences) { + if (callId != confId) { + MapStringString confDetails = CallManager::instance().getConferenceDetails(owner.id, + confId); + // Only hold conference if attached + if (confDetails["CALL_STATE"] == "ACTIVE_DETACHED") + continue; + QStringList callList = CallManager::instance().getParticipantList(owner.id, confId); + if (callList.indexOf(callId) == -1) + CallManager::instance().holdConference(owner.id, confId); + } + } +} + +void +NewCallModel::setConferenceLayout(const QString& confId, const call::Layout& layout) +{ + auto call = pimpl_->calls.find(confId); + if (call != pimpl_->calls.end()) { + switch (layout) { + case call::Layout::GRID: + CallManager::instance().setConferenceLayout(owner.id, confId, 0); + break; + case call::Layout::ONE_WITH_SMALL: + CallManager::instance().setConferenceLayout(owner.id, confId, 1); + break; + case call::Layout::ONE: + CallManager::instance().setConferenceLayout(owner.id, confId, 2); + break; + } + call->second->layout = layout; + } +} + +void +NewCallModel::setActiveParticipant(const QString& confId, const QString& participant) +{ + CallManager::instance().setActiveParticipant(owner.id, confId, participant); +} + +bool +NewCallModel::isModerator(const QString& confId, const QString& uri) +{ + auto call = pimpl_->calls.find(confId); + if (call == pimpl_->calls.end() or not call->second) + return false; + auto participantsModel = pimpl_->participantsModel.find(confId); + if (participantsModel == pimpl_->participantsModel.end() + or participantsModel->second->getParticipants().size() == 0) + return true; + auto ownerUri = owner.profileInfo.uri; + auto uriToCheck = uri; + if (uriToCheck.isEmpty()) { + uriToCheck = ownerUri; + } + auto isModerator = uriToCheck == ownerUri + ? call->second->type == lrc::api::call::Type::CONFERENCE + : false; + if (!isModerator && participantsModel->second->getParticipants().size() != 0) { + if (!uri.isEmpty()) + isModerator = participantsModel->second->checkModerator(uri); + else + isModerator = participantsModel->second->checkModerator(owner.profileInfo.uri); + } + return isModerator; +} + +void +NewCallModel::setModerator(const QString& confId, const QString& peerId, const bool& state) +{ + CallManager::instance().setModerator(owner.id, confId, peerId, state); +} + +bool +NewCallModel::isHandRaised(const QString& confId, const QString& uri) noexcept +{ + auto call = pimpl_->calls.find(confId); + if (call == pimpl_->calls.end() or not call->second) + return false; + + auto participantsModel = pimpl_->participantsModel.find(confId); + if (participantsModel == pimpl_->participantsModel.end()) + return false; + + auto ownerUri = owner.profileInfo.uri; + auto uriToCheck = uri; + if (uriToCheck.isEmpty()) { + uriToCheck = ownerUri; + } + auto handRaised = false; + for (const auto& participant : participantsModel->second->getParticipants()) { + if (participant.uri == uriToCheck) { + handRaised = participant.handRaised; + break; + } + } + return handRaised; +} + +void +NewCallModel::setHandRaised(const QString& accountId, + const QString& confId, + const QString& peerId, + bool state) +{ + auto ownerUri = owner.profileInfo.uri; + auto uriToCheck = peerId; + if (uriToCheck.isEmpty()) { + uriToCheck = ownerUri; + } + CallManager::instance().raiseParticipantHand(accountId, confId, uriToCheck, state); +} + +void +NewCallModel::muteParticipant(const QString& confId, const QString& peerId, const bool& state) +{ + CallManager::instance().muteParticipant(owner.id, confId, peerId, state); +} + +void +NewCallModel::hangupParticipant(const QString& confId, const QString& participant) +{ + CallManager::instance().hangupParticipant(owner.id, confId, participant); +} + +void +NewCallModel::sendSipMessage(const QString& callId, const QString& body) const +{ + MapStringString payloads; + payloads["text/plain"] = body; + + CallManager::instance().sendTextMessage(owner.id, callId, payloads, true /* not used */); +} + +bool +NewCallModel::isConferenceHost(const QString& callId) +{ + auto call = pimpl_->calls.find(callId); + if (call == pimpl_->calls.end() or not call->second) + return false; + else + return call->second->type == lrc::api::call::Type::CONFERENCE; +} + +void +NewCallModelPimpl::slotIncomingCallWithMedia(const QString& accountId, + const QString& callId, + const QString& fromId, + const QString& displayname, + const VectorMapStringString& mediaList) +{ + if (linked.owner.id != accountId) { + return; + } + // TODO: uncomment this. For now, the rendez-vous account is showing calls + // if (linked.owner.confProperties.isRendezVous) { + // // Do not notify for calls if rendez vous because it's in a detached + // // mode and auto answer is managed by the daemon + // return; + //} + + auto callInfo = std::make_shared<call::Info>(); + callInfo->id = callId; + // peer uri = ring:<jami_id> or sip number + auto uri = (linked.owner.profileInfo.type != profile::Type::SIP && !fromId.contains("ring:")) + ? "ring:" + fromId + : fromId; + callInfo->peerUri = uri; + callInfo->isOutgoing = false; + callInfo->status = call::Status::INCOMING_RINGING; + callInfo->type = call::Type::DIALOG; + callInfo->isAudioOnly = true; + callInfo->videoMuted = true; + for (const auto& item : mediaList) { + if (item[MediaAttributeKey::MEDIA_TYPE] == MediaAttributeValue::VIDEO) { + callInfo->isAudioOnly = false; + if (!checkMediaDeviceMuted(item)) { + callInfo->videoMuted = false; + break; + } + } + } + callInfo->mediaList = mediaList; + calls.emplace(callId, std::move(callInfo)); + + if (!linked.owner.confProperties.allowIncoming + && linked.owner.profileInfo.type == profile::Type::JAMI) { + linked.refuse(callId); + return; + } + + Q_EMIT linked.newIncomingCall(fromId, callId, displayname); +} + +void +NewCallModelPimpl::slotMediaChangeRequested(const QString& accountId, + const QString& callId, + const VectorMapStringString& mediaList) +{ + if (linked.owner.id != accountId) { + return; + } + + if (mediaList.empty()) + return; + + auto& callInfo = calls[callId]; + if (!callInfo) + return; + + QList<QString> currentMediaLabels {}; + for (auto& currentItem : callInfo->mediaList) + currentMediaLabels.append(currentItem[MediaAttributeKey::LABEL]); + + auto answerMedia = QList<MapStringString>::fromVector(mediaList); + + for (auto& item : answerMedia) { + int index = currentMediaLabels.indexOf(item[MediaAttributeKey::LABEL]); + if (index >= 0) { + item[MediaAttributeKey::MUTED] = callInfo->mediaList[index][MediaAttributeKey::MUTED]; + item[MediaAttributeKey::ENABLED] = callInfo->mediaList[index][MediaAttributeKey::ENABLED]; + } else { + item[MediaAttributeKey::MUTED] = "true"; + item[MediaAttributeKey::ENABLED] = "true"; + } + } + CallManager::instance().answerMediaChangeRequest(linked.owner.id, + callId, + QVector<MapStringString>::fromList( + answerMedia)); +} + +void +NewCallModelPimpl::slotCallStateChanged(const QString& accountId, + const QString& callId, + const QString& state, + int code) +{ + if (accountId != linked.owner.id || !linked.hasCall(callId)) + return; + + auto status = call::to_status(state); + auto& call = calls[callId]; + if (!call) + return; + + if (status == call::Status::ENDED && !call::isTerminating(call->status)) { + call->status = call::Status::TERMINATING; + Q_EMIT linked.callStatusChanged(callId, code); + Q_EMIT behaviorController.callStatusChanged(linked.owner.id, callId); + } + + // proper state transition + auto previousStatus = call->status; + call->status = status; + + if (previousStatus == call->status) { + // call state didn't change, simply ignore signal + return; + } + + qDebug() << QString("slotCallStateChanged (call: %1), from %2 to %3") + .arg(callId) + .arg(call::to_string(previousStatus)) + .arg(call::to_string(status)); + + // NOTE: signal emission order matters, always emit CallStatusChanged before CallEnded + Q_EMIT linked.callStatusChanged(callId, code); + Q_EMIT behaviorController.callStatusChanged(linked.owner.id, callId); + + if (call->status == call::Status::ENDED) { + Q_EMIT linked.callEnded(callId); + + // Remove from pendingConferences_ + for (int i = 0; i < pendingConferencees_.size(); ++i) { + if (pendingConferencees_.at(i).callId == callId) { + Q_EMIT linked.beginRemovePendingConferenceesRows(i); + pendingConferencees_.removeAt(i); + Q_EMIT linked.endRemovePendingConferenceesRows(); + break; + } + } + } else if (call->status == call::Status::IN_PROGRESS) { + if (previousStatus == call::Status::INCOMING_RINGING + || previousStatus == call::Status::OUTGOING_RINGING) { + if (previousStatus == call::Status::INCOMING_RINGING + && linked.owner.profileInfo.type != profile::Type::SIP + && !linked.owner.confProperties.isRendezVous) { // TODO remove this when we want to + // not show calls in rendez-vous + linked.setCurrentCall(callId); + } + call->startTime = std::chrono::steady_clock::now(); + Q_EMIT linked.callStarted(callId); + sendProfile(callId); + } + // Add to calls if in pendingConferences_ + for (int i = 0; i < pendingConferencees_.size(); ++i) { + if (pendingConferencees_.at(i).callId == callId) { + linked.joinCalls(pendingConferencees_.at(i).callIdToJoin, + pendingConferencees_.at(i).callId); + break; + } + } + } else if (call->status == call::Status::PAUSED) { + currentCall_ = ""; + } +} + +void +NewCallModelPimpl::slotMediaNegotiationStatus(const QString& callId, + const QString&, + const VectorMapStringString& mediaList) +{ + if (!linked.hasCall(callId)) { + return; + } + + auto& callInfo = calls[callId]; + if (!callInfo) { + return; + } + + callInfo->isAudioOnly = true; + callInfo->videoMuted = true; + for (const auto& item : mediaList) { + if (item[MediaAttributeKey::MEDIA_TYPE] == MediaAttributeValue::VIDEO) { + if (item[MediaAttributeKey::ENABLED] == "true") { + callInfo->isAudioOnly = false; + } + callInfo->videoMuted = checkMediaDeviceMuted(item); + } + if (item[MediaAttributeKey::MEDIA_TYPE] == MediaAttributeValue::AUDIO) { + callInfo->audioMuted = checkMediaDeviceMuted(item); + } + } + callInfo->mediaList = mediaList; + if (callInfo->status == call::Status::IN_PROGRESS) + Q_EMIT linked.callInfosChanged(linked.owner.id, callId); +} + +void +NewCallModelPimpl::slotincomingVCardChunk(const QString& accountId, + const QString& callId, + const QString& from, + int part, + int numberOfParts, + const QString& payload) +{ + if (accountId != linked.owner.id || !linked.hasCall(callId)) + return; + + auto it = vcardsChunks.find(from); + if (it != vcardsChunks.end()) { + vcardsChunks[from][part - 1] = payload; + + if (not std::any_of(vcardsChunks[from].begin(), + vcardsChunks[from].end(), + [](const auto& s) { return s.isEmpty(); })) { + profile::Info profileInfo; + profileInfo.uri = from; + profileInfo.type = profile::Type::JAMI; + + QString vcardPhoto; + + for (auto& chunk : vcardsChunks[from]) + vcardPhoto += chunk; + + for (auto& e : QString(vcardPhoto).split("\n")) + if (e.contains("PHOTO")) + profileInfo.avatar = e.split(":")[1]; + else if (e.contains("FN")) + profileInfo.alias = e.split(":")[1]; + + contact::Info contactInfo; + contactInfo.profileInfo = profileInfo; + + linked.owner.contactModel->addContact(contactInfo); + if (!lrc::api::Lrc::cacheAvatars.load()) + contactInfo.profileInfo.avatar.clear(); + vcardsChunks.erase(from); // Transfer is finish, we don't want to reuse this entry. + } + } else { + vcardsChunks[from] = VectorString(numberOfParts); + vcardsChunks[from][part - 1] = payload; + } +} + +void +NewCallModelPimpl::slotVoiceMailNotify(const QString& accountId, + int newCount, + int oldCount, + int urgentCount) +{ + Q_EMIT linked.voiceMailNotify(accountId, newCount, oldCount, urgentCount); +} + +void +NewCallModelPimpl::slotOnConferenceInfosUpdated(const QString& confId, + const VectorMapStringString& infos) +{ + auto it = calls.find(confId); + if (it == calls.end() or not it->second) + return; + + auto participantIt = participantsModel.find(confId); + if (participantIt == participantsModel.end()) + participantIt = participantsModel + .emplace(confId, + std::make_shared<CallParticipants>(infos, confId, linked)) + .first; + else + participantIt->second->update(infos); + it->second->layout = participantIt->second->getLayout(); + + // if Jami, remove @ring.dht + for (auto& i : participantIt->second->getParticipants()) { + i.uri.replace("@ring.dht", ""); + if (i.uri.isEmpty()) { + if (it->second->type == call::Type::CONFERENCE) { + i.uri = linked.owner.profileInfo.uri; + } else { + i.uri = it->second->peerUri.replace("ring:", ""); + } + } + } + + Q_EMIT linked.callInfosChanged(linked.owner.id, confId); + Q_EMIT linked.onParticipantsChanged(confId); + + for (auto& info : infos) { + if (info["uri"].isEmpty()) { + it->second->videoMuted = info["videoMuted"] == "true"; + it->second->audioMuted = info["audioLocalMuted"] == "true"; + } + } + + // TODO: remove when the rendez-vous UI will be done + // For now, the rendez-vous account can see ongoing calls + // And must be notified when a new + QStringList callList = CallManager::instance().getParticipantList(linked.owner.id, confId); + Q_FOREACH (const auto& call, callList) { + Q_EMIT linked.callAddedToConference(call, confId); + calls[call]->videoMuted = it->second->videoMuted; + calls[call]->audioMuted = it->second->audioMuted; + Q_EMIT linked.callInfosChanged(linked.owner.id, call); + } +} + +bool +NewCallModel::hasCall(const QString& callId) const +{ + return pimpl_->calls.find(callId) != pimpl_->calls.end(); +} + +void +NewCallModelPimpl::slotConferenceCreated(const QString& accountId, const QString& confId) +{ + if (accountId != linked.owner.id) + return; + // Detect if conference is created for this account + QStringList callList = CallManager::instance().getParticipantList(linked.owner.id, confId); + auto hasConference = false; + Q_FOREACH (const auto& call, callList) { + hasConference |= linked.hasCall(call); + } + if (!hasConference) + return; + + auto callInfo = std::make_shared<call::Info>(); + callInfo->id = confId; + callInfo->status = call::Status::IN_PROGRESS; + callInfo->type = call::Type::CONFERENCE; + callInfo->startTime = std::chrono::steady_clock::now(); + + VectorMapStringString infos = CallManager::instance().getConferenceInfos(linked.owner.id, + confId); + auto participantsPtr = std::make_shared<CallParticipants>(infos, confId, linked); + callInfo->layout = participantsPtr->getLayout(); + participantsModel[confId] = participantsPtr; + + calls[confId] = callInfo; + + Q_FOREACH (const auto& call, callList) { + Q_EMIT linked.callAddedToConference(call, confId); + // Remove call from pendingConferences_ + for (int i = 0; i < pendingConferencees_.size(); ++i) { + if (pendingConferencees_.at(i).callId == call) { + Q_EMIT linked.beginRemovePendingConferenceesRows(i); + pendingConferencees_.removeAt(i); + Q_EMIT linked.endRemovePendingConferenceesRows(); + break; + } + } + } +} + +void +NewCallModelPimpl::sendProfile(const QString& callId) +{ + auto vCard = linked.owner.accountModel->accountVCard(linked.owner.id); + + std::random_device rdev; + auto key = std::to_string(dis(rdev)); + + int i = 0; + int total = vCard.size() / 1000 + (vCard.size() % 1000 ? 1 : 0); + while (vCard.size()) { + auto sizeLimit = std::min(1000, static_cast<int>(vCard.size())); + MapStringString chunk; + chunk[QString("%1; id=%2,part=%3,of=%4") + .arg(lrc::vCard::PROFILE_VCF) + .arg(key.c_str()) + .arg(QString::number(i + 1)) + .arg(QString::number(total))] + = vCard.left(sizeLimit); + vCard.remove(0, sizeLimit); + ++i; + CallManager::instance().sendTextMessage(linked.owner.id, callId, chunk, false); + } +} + +void +NewCallModelPimpl::remoteRecordingChanged(const QString& callId, + const QString& peerNumber, + bool state) +{ + auto it = calls.find(callId); + if (it == calls.end() or not it->second) + return; + + auto uri = peerNumber; + + if (uri.contains("ring:")) + uri.remove("ring:"); + if (uri.contains("jami:")) + uri.remove("jami:"); + if (uri.contains("@ring.dht")) + uri.remove("@ring.dht"); + + // Add peer to peerRec set + if (state && not it->second->peerRec.contains(uri)) + it->second->peerRec.insert(uri); + + // remove peer from peerRec set + if (!state && it->second->peerRec.contains(uri)) + it->second->peerRec.remove(uri); + + Q_EMIT linked.remoteRecordingChanged(callId, it->second->peerRec, state); +} + +void +NewCallModelPimpl::onDecodingStarted(const QString& id, + const QString& shmPath, + int width, + int height) +{ + lrc.getAVModel().addRenderer(id, QSize(width, height), shmPath); +} + +} // namespace lrc + +#include "api/moc_newcallmodel.cpp" +#include "newcallmodel.moc" diff --git a/src/libclient/newcodecmodel.cpp b/src/libclient/newcodecmodel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f0ab1bd8542562d330112ecbf558bcbaa67ddb46 --- /dev/null +++ b/src/libclient/newcodecmodel.cpp @@ -0,0 +1,380 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#include "api/newcodecmodel.h" + +// LRC +#include "callbackshandler.h" +#include "dbus/configurationmanager.h" + +// Daemon +#include <account_const.h> + +// Qt +#include <QObject> +#include <QList> + +// std +#include <mutex> + +namespace lrc { + +using namespace api; + +class NewCodecModelPimpl : public QObject +{ + Q_OBJECT +public: + NewCodecModelPimpl(const NewCodecModel& linked, const CallbacksHandler& callbacksHandler); + ~NewCodecModelPimpl(); + + void loadFromDaemon(); + + QVector<unsigned int> codecsList_; + QList<Codec> videoCodecs; + std::mutex audioCodecsMtx; + QList<Codec> audioCodecs; + std::mutex videoCodecsMtx; + + const CallbacksHandler& callbacksHandler; + const NewCodecModel& linked; + + void setActiveCodecs(); + void setCodecDetails(const Codec& codec, bool isAudio); + +private: + void addCodec(const unsigned int& id, const QVector<unsigned int>& activeCodecs); +}; + +NewCodecModel::NewCodecModel(const account::Info& owner, const CallbacksHandler& callbacksHandler) + : owner(owner) + , pimpl_(std::make_unique<NewCodecModelPimpl>(*this, callbacksHandler)) +{} + +NewCodecModel::~NewCodecModel() {} + +QList<Codec> +NewCodecModel::getAudioCodecs() const +{ + return pimpl_->audioCodecs; +} + +QList<Codec> +NewCodecModel::getVideoCodecs() const +{ + return pimpl_->videoCodecs; +} + +void +NewCodecModel::increasePriority(const unsigned int& codecId, bool isVideo) +{ + auto& codecs = isVideo ? pimpl_->videoCodecs : pimpl_->audioCodecs; + auto& mutex = isVideo ? pimpl_->videoCodecsMtx : pimpl_->audioCodecsMtx; + { + std::unique_lock<std::mutex> lock(mutex); + auto it = codecs.begin(); + if (codecs.begin()->id == codecId) { + // Already at top, abort + return; + } + while (it != codecs.end()) { + if (it->id == codecId) { + std::iter_swap(it, std::prev(it)); + break; + } + it++; + } + } + pimpl_->setActiveCodecs(); +} + +void +NewCodecModel::decreasePriority(const unsigned int& codecId, bool isVideo) +{ + auto& codecs = isVideo ? pimpl_->videoCodecs : pimpl_->audioCodecs; + auto& mutex = isVideo ? pimpl_->videoCodecsMtx : pimpl_->audioCodecsMtx; + { + std::unique_lock<std::mutex> lock(mutex); + auto it = codecs.begin(); + if (codecs.size() > 0 && (codecs.end() - 1)->id == codecId) { + // Already at bottom, abort + return; + } + while (it != codecs.end()) { + if (it->id == codecId) { + std::iter_swap(it, std::next(it)); + break; + } + it++; + } + } + pimpl_->setActiveCodecs(); +} + +bool +NewCodecModel::enable(const unsigned int& codecId, bool enabled) +{ + auto redraw = false; + auto isAudio = true; + { + std::unique_lock<std::mutex> lock(pimpl_->videoCodecsMtx); + auto allDisabled = true; + for (auto& codec : pimpl_->videoCodecs) { + if (codec.id == codecId) { + if (codec.enabled == enabled) + return redraw; + codec.enabled = enabled; + isAudio = false; + } + if (codec.enabled) { + allDisabled = false; + } + } + if (allDisabled) { + redraw = true; + } + } + if (isAudio) { + std::unique_lock<std::mutex> lock(pimpl_->audioCodecsMtx); + auto allDisabled = true; + for (auto& codec : pimpl_->audioCodecs) { + if (codec.id == codecId) { + if (codec.enabled == enabled) + return redraw; + codec.enabled = enabled; + } + if (codec.enabled) { + allDisabled = false; + } + } + if (allDisabled) { + redraw = true; + } + } + pimpl_->setActiveCodecs(); + return redraw; +} + +void +NewCodecModel::autoQuality(const unsigned int& codecId, bool on) +{ + auto isAudio = true; + Codec finalCodec; + { + std::unique_lock<std::mutex> lock(pimpl_->videoCodecsMtx); + for (auto& codec : pimpl_->videoCodecs) { + if (codec.id == codecId) { + if (codec.auto_quality_enabled == on) + return; + codec.auto_quality_enabled = on; + isAudio = false; + finalCodec = codec; + break; + } + } + } + if (isAudio) { + std::unique_lock<std::mutex> lock(pimpl_->audioCodecsMtx); + for (auto& codec : pimpl_->audioCodecs) { + if (codec.id == codecId) { + if (codec.auto_quality_enabled == on) + return; + codec.auto_quality_enabled = on; + finalCodec = codec; + break; + } + } + } + pimpl_->setCodecDetails(finalCodec, isAudio); +} + +void +NewCodecModel::quality(const unsigned int& codecId, double quality) +{ + auto isAudio = true; + auto qualityStr = toQString(static_cast<int>(quality)); + Codec finalCodec; + { + std::unique_lock<std::mutex> lock(pimpl_->videoCodecsMtx); + for (auto& codec : pimpl_->videoCodecs) { + if (codec.id == codecId) { + if (codec.quality == qualityStr) + return; + codec.quality = qualityStr; + isAudio = false; + finalCodec = codec; + break; + } + } + } + if (isAudio) { + std::unique_lock<std::mutex> lock(pimpl_->audioCodecsMtx); + for (auto& codec : pimpl_->audioCodecs) { + if (codec.id == codecId) { + if (codec.quality == qualityStr) + return; + codec.quality = qualityStr; + finalCodec = codec; + break; + } + } + } + pimpl_->setCodecDetails(finalCodec, isAudio); +} + +void +NewCodecModel::bitrate(const unsigned int& codecId, double bitrate) +{ + auto isAudio = true; + auto bitrateStr = toQString(static_cast<int>(bitrate)); + Codec finalCodec; + { + std::unique_lock<std::mutex> lock(pimpl_->videoCodecsMtx); + for (auto& codec : pimpl_->videoCodecs) { + if (codec.id == codecId) { + if (codec.bitrate == bitrateStr) + return; + codec.bitrate = bitrateStr; + isAudio = false; + finalCodec = codec; + break; + } + } + } + if (isAudio) { + std::unique_lock<std::mutex> lock(pimpl_->audioCodecsMtx); + for (auto& codec : pimpl_->audioCodecs) { + if (codec.id == codecId) { + if (codec.bitrate == bitrateStr) + return; + codec.bitrate = bitrateStr; + finalCodec = codec; + break; + } + } + } + pimpl_->setCodecDetails(finalCodec, isAudio); +} + +NewCodecModelPimpl::NewCodecModelPimpl(const NewCodecModel& linked, + const CallbacksHandler& callbacksHandler) + : linked(linked) + , callbacksHandler(callbacksHandler) +{ + codecsList_ = ConfigurationManager::instance().getCodecList(); + loadFromDaemon(); +} + +NewCodecModelPimpl::~NewCodecModelPimpl() {} + +void +NewCodecModelPimpl::loadFromDaemon() +{ + { + std::unique_lock<std::mutex> lock(audioCodecsMtx); + audioCodecs.clear(); + } + { + std::unique_lock<std::mutex> lock(videoCodecsMtx); + videoCodecs.clear(); + } + QVector<unsigned int> activeCodecs = ConfigurationManager::instance().getActiveCodecList( + linked.owner.id); + for (const auto& id : activeCodecs) { + addCodec(id, activeCodecs); + } + for (const auto& id : codecsList_) { + if (activeCodecs.indexOf(id) != -1) + continue; + addCodec(id, activeCodecs); + } +} + +void +NewCodecModelPimpl::setActiveCodecs() +{ + QVector<unsigned int> enabledCodecs; + { + std::unique_lock<std::mutex> lock(videoCodecsMtx); + for (auto& codec : videoCodecs) { + if (codec.enabled) { + enabledCodecs.push_back(codec.id); + } + } + } + { + std::unique_lock<std::mutex> lock(audioCodecsMtx); + for (auto& codec : audioCodecs) { + if (codec.enabled) { + enabledCodecs.push_back(codec.id); + } + } + } + ConfigurationManager::instance().setActiveCodecList(linked.owner.id, enabledCodecs); + // Refresh list from daemon + loadFromDaemon(); +} + +void +NewCodecModelPimpl::addCodec(const unsigned int& id, const QVector<unsigned int>& activeCodecs) +{ + MapStringString details = ConfigurationManager::instance().getCodecDetails(linked.owner.id, id); + Codec codec; + codec.id = id; + codec.enabled = activeCodecs.indexOf(id) != -1; + codec.name = details[DRing::Account::ConfProperties::CodecInfo::NAME]; + codec.samplerate = details[DRing::Account::ConfProperties::CodecInfo::SAMPLE_RATE]; + codec.bitrate = details[DRing::Account::ConfProperties::CodecInfo::BITRATE]; + codec.min_bitrate = details[DRing::Account::ConfProperties::CodecInfo::MIN_BITRATE]; + codec.max_bitrate = details[DRing::Account::ConfProperties::CodecInfo::MAX_BITRATE]; + codec.type = details[DRing::Account::ConfProperties::CodecInfo::TYPE]; + codec.quality = details[DRing::Account::ConfProperties::CodecInfo::QUALITY]; + codec.min_quality = details[DRing::Account::ConfProperties::CodecInfo::MIN_QUALITY]; + codec.max_quality = details[DRing::Account::ConfProperties::CodecInfo::MAX_QUALITY]; + codec.auto_quality_enabled + = details[DRing::Account::ConfProperties::CodecInfo::AUTO_QUALITY_ENABLED] == "true"; + if (codec.type == "AUDIO") { + std::unique_lock<std::mutex> lock(audioCodecsMtx); + audioCodecs.push_back(codec); + } else { + std::unique_lock<std::mutex> lock(videoCodecsMtx); + videoCodecs.push_back(codec); + } +} + +void +NewCodecModelPimpl::setCodecDetails(const Codec& codec, bool isAudio) +{ + MapStringString details; + details[DRing::Account::ConfProperties::CodecInfo::NAME] = codec.name; + details[DRing::Account::ConfProperties::CodecInfo::SAMPLE_RATE] = codec.samplerate; + details[DRing::Account::ConfProperties::CodecInfo::BITRATE] = codec.bitrate; + details[DRing::Account::ConfProperties::CodecInfo::MIN_BITRATE] = codec.min_bitrate; + details[DRing::Account::ConfProperties::CodecInfo::MAX_BITRATE] = codec.max_bitrate; + details[DRing::Account::ConfProperties::CodecInfo::TYPE] = isAudio ? "AUDIO" : "VIDEO"; + details[DRing::Account::ConfProperties::CodecInfo::QUALITY] = codec.quality; + details[DRing::Account::ConfProperties::CodecInfo::MIN_QUALITY] = codec.min_quality; + details[DRing::Account::ConfProperties::CodecInfo::MAX_QUALITY] = codec.max_quality; + details[DRing::Account::ConfProperties::CodecInfo::AUTO_QUALITY_ENABLED] + = codec.auto_quality_enabled ? "true" : "false"; + ConfigurationManager::instance().setCodecDetails(linked.owner.id, codec.id, details); +} + +} // namespace lrc + +#include "newcodecmodel.moc" +#include "api/moc_newcodecmodel.cpp" diff --git a/src/libclient/newdevicemodel.cpp b/src/libclient/newdevicemodel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e1a9f2d1cf7bdbf1da62f70f12b8130148068c97 --- /dev/null +++ b/src/libclient/newdevicemodel.cpp @@ -0,0 +1,243 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#include "api/newdevicemodel.h" + +#include "api/newaccountmodel.h" +#include "callbackshandler.h" +#include "dbus/configurationmanager.h" + +#include <account_const.h> + +#include <QObject> + +#include <list> +#include <mutex> + +namespace lrc { + +using namespace api; + +class NewDeviceModelPimpl : public QObject +{ + Q_OBJECT +public: + NewDeviceModelPimpl(const NewDeviceModel& linked, const CallbacksHandler& callbacksHandler); + ~NewDeviceModelPimpl(); + + const CallbacksHandler& callbacksHandler; + const NewDeviceModel& linked; + + std::mutex devicesMtx_; + QString currentDeviceId_; + QList<Device> devices_; +public Q_SLOTS: + /** + * Listen from CallbacksHandler to get when a device name changed or a device is added + * @param accountId interaction receiver. + * @param devices A map of device IDs with corresponding labels. + */ + void slotKnownDevicesChanged(const QString& accountId, const MapStringString devices); + + /** + * update devices_ when a device is revoked + * @param accountId + * @param deviceId + * @param status SUCCESS = 0, WRONG_PASSWORD = 1, UNKNOWN_DEVICE = 2 + */ + void slotDeviceRevocationEnded(const QString& accountId, + const QString& deviceId, + const int status); +}; + +NewDeviceModel::NewDeviceModel(const account::Info& owner, const CallbacksHandler& callbacksHandler) + : owner(owner) + , pimpl_(std::make_unique<NewDeviceModelPimpl>(*this, callbacksHandler)) +{} + +NewDeviceModel::~NewDeviceModel() {} + +QList<Device> +NewDeviceModel::getAllDevices() const +{ + return pimpl_->devices_; +} + +Device +NewDeviceModel::getDevice(const QString& id) const +{ + std::lock_guard<std::mutex> lock(pimpl_->devicesMtx_); + auto i = std::find_if(pimpl_->devices_.begin(), pimpl_->devices_.end(), [id](const Device& d) { + return d.id == id; + }); + + if (i == pimpl_->devices_.end()) + return {}; + + return *i; +} + +void +NewDeviceModel::revokeDevice(const QString& id, const QString& password) +{ + ConfigurationManager::instance().revokeDevice(owner.id, password, id); +} + +void +NewDeviceModel::setCurrentDeviceName(const QString& newName) +{ + // Update deamon config + auto config = owner.accountModel->getAccountConfig(owner.id); + config.deviceName = newName; + owner.accountModel->setAccountConfig(owner.id, config); + // Update model + std::lock_guard<std::mutex> lock(pimpl_->devicesMtx_); + for (auto& device : pimpl_->devices_) { + if (device.id == config.deviceId) { + device.name = newName; + Q_EMIT deviceUpdated(device.id); + + return; + } + } +} + +NewDeviceModelPimpl::NewDeviceModelPimpl(const NewDeviceModel& linked, + const CallbacksHandler& callbacksHandler) + : linked(linked) + , callbacksHandler(callbacksHandler) + , devices_({}) +{ + const MapStringString aDetails = ConfigurationManager::instance().getAccountDetails( + linked.owner.id); + currentDeviceId_ = aDetails.value(DRing::Account::ConfProperties::DEVICE_ID); + const MapStringString accountDevices = ConfigurationManager::instance().getKnownRingDevices( + linked.owner.id); + auto it = accountDevices.begin(); + while (it != accountDevices.end()) { + { + std::lock_guard<std::mutex> lock(devicesMtx_); + auto device = Device {/* id= */ it.key(), + /* name= */ it.value(), + /* isCurrent= */ it.key() == currentDeviceId_}; + if (device.isCurrent) { + devices_.push_back(device); + } else { + devices_.push_back(device); + } + } + ++it; + } + + connect(&callbacksHandler, + &CallbacksHandler::knownDevicesChanged, + this, + &NewDeviceModelPimpl::slotKnownDevicesChanged); + connect(&callbacksHandler, + &CallbacksHandler::deviceRevocationEnded, + this, + &NewDeviceModelPimpl::slotDeviceRevocationEnded); +} + +NewDeviceModelPimpl::~NewDeviceModelPimpl() +{ + disconnect(&callbacksHandler, + &CallbacksHandler::knownDevicesChanged, + this, + &NewDeviceModelPimpl::slotKnownDevicesChanged); + disconnect(&callbacksHandler, + &CallbacksHandler::deviceRevocationEnded, + this, + &NewDeviceModelPimpl::slotDeviceRevocationEnded); +} + +void +NewDeviceModelPimpl::slotKnownDevicesChanged(const QString& accountId, const MapStringString devices) +{ + if (accountId != linked.owner.id) + return; + auto devicesMap = devices; + // Update current devices + QStringList updatedDevices; + { + std::lock_guard<std::mutex> lock(devicesMtx_); + for (auto& device : devices_) { + if (devicesMap.find(device.id) != devicesMap.end()) { + if (device.name != devicesMap[device.id]) { + updatedDevices.push_back(device.id); + device.name = devicesMap[device.id]; + } + devicesMap.remove(device.id); + } + } + } + for (const auto& device : updatedDevices) + Q_EMIT linked.deviceUpdated(device); + + // Add new devices + QStringList addedDevices; + { + std::lock_guard<std::mutex> lock(devicesMtx_); + auto it = devicesMap.begin(); + while (it != devicesMap.end()) { + devices_.push_back(Device {/* id= */ it.key(), + /* name= */ it.value(), + /* isCurrent= */ false}); + addedDevices.push_back(it.key()); + ++it; + } + } + for (const auto& device : addedDevices) + Q_EMIT linked.deviceAdded(device); +} + +void +NewDeviceModelPimpl::slotDeviceRevocationEnded(const QString& accountId, + const QString& deviceId, + const int status) +{ + if (accountId != linked.owner.id) + return; + if (status == 0) { + std::lock_guard<std::mutex> lock(devicesMtx_); + auto it = std::find_if(devices_.begin(), devices_.end(), [deviceId](const Device& d) { + return d.id == deviceId; + }); + + if (it != devices_.end()) + devices_.erase(it); + } + + switch (status) { + case 0: + Q_EMIT linked.deviceRevoked(deviceId, NewDeviceModel::Status::SUCCESS); + break; + case 1: + Q_EMIT linked.deviceRevoked(deviceId, NewDeviceModel::Status::WRONG_PASSWORD); + break; + case 2: + Q_EMIT linked.deviceRevoked(deviceId, NewDeviceModel::Status::UNKNOWN_DEVICE); + break; + default: + break; + } +} + +} // namespace lrc + +#include "newdevicemodel.moc" +#include "api/moc_newdevicemodel.cpp" diff --git a/src/libclient/peerdiscoverymodel.cpp b/src/libclient/peerdiscoverymodel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8094ae9503dfd80988c8ef80cd1ab8c80a6aedf2 --- /dev/null +++ b/src/libclient/peerdiscoverymodel.cpp @@ -0,0 +1,118 @@ +/**************************************************************************** + * Copyright (C) 2019-2022 Savoir-faire Linux Inc. * + * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#include "api/peerdiscoverymodel.h" + +// new LRC +#include "callbackshandler.h" + +// Dbus +#include "dbus/configurationmanager.h" + +namespace lrc { + +using namespace api; + +class PeerDiscoveryModelPimpl : public QObject +{ + Q_OBJECT +public: + PeerDiscoveryModelPimpl(PeerDiscoveryModel& linked, + const CallbacksHandler& callbackHandler, + const QString& accountID); + ~PeerDiscoveryModelPimpl(); + + PeerDiscoveryModel& linked_; + const CallbacksHandler& callbacksHandler_; + const QString accountID_; + +public Q_SLOTS: + + /** + * Emit peerMapStatusChanged. + * @param accountId + * @param status + */ + void slotPeerMapStatusChanged(const QString& accountID, + const QString& contactUri, + int state, + const QString& displayname); +}; + +PeerDiscoveryModel::PeerDiscoveryModel(const CallbacksHandler& callbacksHandler, + const QString& accountID) + : QObject() + , pimpl_(std::make_unique<PeerDiscoveryModelPimpl>(*this, callbacksHandler, accountID)) +{} + +PeerDiscoveryModel::~PeerDiscoveryModel() {} + +PeerDiscoveryModelPimpl::PeerDiscoveryModelPimpl(PeerDiscoveryModel& linked, + const CallbacksHandler& callbacksHandler, + const QString& accountID) + : linked_(linked) + , callbacksHandler_(callbacksHandler) + , accountID_(accountID) +{ + connect(&callbacksHandler_, + &CallbacksHandler::newPeerSubscription, + this, + &PeerDiscoveryModelPimpl::slotPeerMapStatusChanged); +} + +PeerDiscoveryModelPimpl::~PeerDiscoveryModelPimpl() +{ + disconnect(&callbacksHandler_, + &CallbacksHandler::newPeerSubscription, + this, + &PeerDiscoveryModelPimpl::slotPeerMapStatusChanged); +} + +void +PeerDiscoveryModelPimpl::slotPeerMapStatusChanged(const QString& accountID, + const QString& contactUri, + int state, + const QString& displayname) +{ + if (accountID != accountID_) { + return; + } + Q_EMIT linked_.modelChanged(contactUri, + state == 0 ? PeerModelChanged::INSERT : PeerModelChanged::REMOVE, + displayname); +} + +std::vector<PeerContact> +PeerDiscoveryModel::getNearbyPeers() const +{ + std::vector<PeerContact> result; + const MapStringString nearbyPeers = ConfigurationManager::instance().getNearbyPeers( + pimpl_->accountID_); + result.reserve(nearbyPeers.size()); + + QMap<QString, QString>::const_iterator i = nearbyPeers.constBegin(); + while (i != nearbyPeers.constEnd()) { + result.emplace_back(PeerContact {i.key().toStdString(), i.value().toStdString()}); + ++i; + } + return result; +} + +} // namespace lrc + +#include "api/moc_peerdiscoverymodel.cpp" +#include "peerdiscoverymodel.moc" diff --git a/src/libclient/pixmapmanipulatordefault.cpp b/src/libclient/pixmapmanipulatordefault.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cae0fa8ae7c7b95f028d5e459f527f830ceec84a --- /dev/null +++ b/src/libclient/pixmapmanipulatordefault.cpp @@ -0,0 +1,95 @@ +/**************************************************************************** + * Copyright (C) 2013-2022 Savoir-faire Linux Inc. * + * Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#include "pixmapmanipulatordefault.h" + +// Qt +#include <QtCore/QSize> +#include <QtCore/QVariant> +#include <QtCore/QModelIndex> + +// LRC +#include "api/account.h" +#include "api/conversation.h" + +namespace Interfaces { + +QVariant +PixmapManipulatorDefault::numberCategoryIcon(const QVariant& p, + const QSize& size, + bool displayPresence, + bool isPresent) +{ + Q_UNUSED(p) + Q_UNUSED(size) + Q_UNUSED(displayPresence) + Q_UNUSED(isPresent) + return QVariant(); +} + +QVariant +PixmapManipulatorDefault::conversationPhoto(const lrc::api::conversation::Info& conversation, + const lrc::api::account::Info& accountInfo, + const QSize& size, + bool displayPresence) +{ + Q_UNUSED(conversation) + Q_UNUSED(accountInfo) + Q_UNUSED(size) + Q_UNUSED(displayPresence) + return QVariant(); +} + +QByteArray +PixmapManipulatorDefault::toByteArray(const QVariant& pxm) +{ + Q_UNUSED(pxm) + return QByteArray(); +} + +QVariant +PixmapManipulatorDefault::personPhoto(const QByteArray& data, const QString& type) +{ + Q_UNUSED(data) + Q_UNUSED(type) + return QVariant(); +} + +QVariant +PixmapManipulatorDefault::userActionIcon(const UserActionElement& state) const +{ + Q_UNUSED(state) + return QVariant(); +} + +QVariant +PixmapManipulatorDefault::decorationRole(const QModelIndex& index) +{ + Q_UNUSED(index) + return QVariant(); +} + +QVariant +PixmapManipulatorDefault::decorationRole(const lrc::api::conversation::Info& conversation, + const lrc::api::account::Info& accountInfo) +{ + Q_UNUSED(conversation) + Q_UNUSED(accountInfo) + return QVariant(); +} + +} // namespace Interfaces diff --git a/src/libclient/pixmapmanipulatordefault.h b/src/libclient/pixmapmanipulatordefault.h new file mode 100644 index 0000000000000000000000000000000000000000..8734b22e1cd53618148926a6a5c2efc6d2ec104c --- /dev/null +++ b/src/libclient/pixmapmanipulatordefault.h @@ -0,0 +1,48 @@ +/**************************************************************************** + * Copyright (C) 2013-2022 Savoir-faire Linux Inc. * + * Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#include "interfaces/pixmapmanipulatori.h" + +namespace Interfaces { + +/// Default implementation of the PixmapManipulator interface which simply returns empty +/// QVariants/QByteArrays +class LIB_EXPORT PixmapManipulatorDefault : public PixmapManipulatorI +{ +public: + QVariant conversationPhoto(const lrc::api::conversation::Info& conversation, + const lrc::api::account::Info& accountInfo, + const QSize& size, + bool displayPresence = true) override; + QVariant numberCategoryIcon(const QVariant& p, + const QSize& size, + bool displayPresence = false, + bool isPresent = false) override; + QByteArray toByteArray(const QVariant& pxm) override; + QVariant personPhoto(const QByteArray& data, const QString& type = "PNG") override; + QVariant decorationRole(const QModelIndex& index) override; + QVariant decorationRole(const lrc::api::conversation::Info& conversation, + const lrc::api::account::Info& accountInfo) override; + /** + * Return the icons associated with the action and its state + */ + QVariant userActionIcon(const UserActionElement& state) const override; +}; + +} // namespace Interfaces diff --git a/src/libclient/pluginmodel.cpp b/src/libclient/pluginmodel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9845089fdb8d11cd79eef48f104dcb7ca3d48ed1 --- /dev/null +++ b/src/libclient/pluginmodel.cpp @@ -0,0 +1,254 @@ +/** + * Copyright (C) 2020-2022 Savoir-faire Linux Inc. + * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include "api/pluginmodel.h" + +// Std +#include <algorithm> // std::sort +#include <chrono> +#include <csignal> +#include <iomanip> // for std::put_time +#include <fstream> +#include <mutex> +#include <thread> +#include <string> +#include <sstream> + +// Qt +#include <QtCore/QStandardPaths> +#include <QtCore/QDir> +#include <QUrl> + +// Ring daemon + +// LRC +#include "dbus/pluginmanager.h" + +namespace lrc { + +using namespace api; + +PluginModel::PluginModel() + : QObject() +{} + +PluginModel::~PluginModel() {} + +void +PluginModel::setPluginsEnabled(bool enable) +{ + PluginManager::instance().setPluginsEnabled(enable); + if (!enable) + Q_EMIT chatHandlerStatusUpdated(false); + else + Q_EMIT chatHandlerStatusUpdated(getChatHandlers().size() > 0); + + Q_EMIT modelUpdated(); +} + +bool +PluginModel::getPluginsEnabled() const +{ + return PluginManager::instance().getPluginsEnabled(); +} + +VectorString +PluginModel::getInstalledPlugins() const +{ + return VectorString::fromList(PluginManager::instance().getInstalledPlugins()); +} + +VectorString +PluginModel::getLoadedPlugins() const +{ + return VectorString::fromList(PluginManager::instance().getLoadedPlugins()); +} + +plugin::PluginDetails +PluginModel::getPluginDetails(const QString& path) +{ + if (path.isEmpty()) { + return plugin::PluginDetails(); + } + MapStringString details = PluginManager::instance().getPluginDetails(path); + plugin::PluginDetails result; + if (!details.empty()) { + result.name = details["name"]; + result.path = path; + result.iconPath = details["iconPath"]; + } + + VectorString loadedPlugins = getLoadedPlugins(); + if (std::find(loadedPlugins.begin(), loadedPlugins.end(), result.path) != loadedPlugins.end()) { + result.loaded = true; + } + + return result; +} + +bool +PluginModel::installPlugin(const QString& jplPath, bool force) +{ + if (getPluginsEnabled()) { + auto result = PluginManager::instance().installPlugin(jplPath, force); + Q_EMIT modelUpdated(); + return result; + } + return false; +} + +bool +PluginModel::uninstallPlugin(const QString& rootPath) +{ + auto result = PluginManager::instance().uninstallPlugin(rootPath); + Q_EMIT modelUpdated(); + return result; +} + +bool +PluginModel::loadPlugin(const QString& path) +{ + bool status = PluginManager::instance().loadPlugin(path); + Q_EMIT modelUpdated(); + if (getChatHandlers().size() > 0) + Q_EMIT chatHandlerStatusUpdated(getPluginsEnabled()); + return status; +} + +bool +PluginModel::unloadPlugin(const QString& path) +{ + bool status = PluginManager::instance().unloadPlugin(path); + Q_EMIT modelUpdated(); + if (getChatHandlers().size() <= 0) + Q_EMIT chatHandlerStatusUpdated(false); + return status; +} + +VectorString +PluginModel::getCallMediaHandlers() const +{ + return VectorString::fromList(PluginManager::instance().getCallMediaHandlers()); +} + +void +PluginModel::toggleCallMediaHandler(const QString& mediaHandlerId, + const QString& callId, + bool toggle) +{ + PluginManager::instance().toggleCallMediaHandler(mediaHandlerId, callId, toggle); + Q_EMIT modelUpdated(); +} + +VectorString +PluginModel::getChatHandlers() const +{ + return VectorString::fromList(PluginManager::instance().getChatHandlers()); +} + +void +PluginModel::toggleChatHandler(const QString& chatHandlerId, + const QString& accountId, + const QString& peerId, + bool toggle) +{ + PluginManager::instance().toggleChatHandler(chatHandlerId, accountId, peerId, toggle); + Q_EMIT modelUpdated(); +} + +VectorString +PluginModel::getCallMediaHandlerStatus(const QString& callId) +{ + return VectorString::fromList(PluginManager::instance().getCallMediaHandlerStatus(callId)); +} + +plugin::PluginHandlerDetails +PluginModel::getCallMediaHandlerDetails(const QString& mediaHandlerId) +{ + if (mediaHandlerId.isEmpty()) { + return plugin::PluginHandlerDetails(); + } + MapStringString mediaHandlerDetails = PluginManager::instance().getCallMediaHandlerDetails( + mediaHandlerId); + plugin::PluginHandlerDetails result; + if (!mediaHandlerDetails.empty()) { + result.id = mediaHandlerId; + result.iconPath = mediaHandlerDetails["iconPath"]; + result.name = mediaHandlerDetails["name"]; + result.pluginId = mediaHandlerDetails["pluginId"]; + } + + return result; +} + +VectorString +PluginModel::getChatHandlerStatus(const QString& accountId, const QString& peerId) +{ + return VectorString::fromList(PluginManager::instance().getChatHandlerStatus(accountId, peerId)); +} + +plugin::PluginHandlerDetails +PluginModel::getChatHandlerDetails(const QString& chatHandlerId) +{ + if (chatHandlerId.isEmpty()) { + return plugin::PluginHandlerDetails(); + } + MapStringString chatHandlerDetails = PluginManager::instance().getChatHandlerDetails( + chatHandlerId); + plugin::PluginHandlerDetails result; + if (!chatHandlerDetails.empty()) { + result.id = chatHandlerId; + result.iconPath = chatHandlerDetails["iconPath"]; + result.name = chatHandlerDetails["name"]; + result.pluginId = chatHandlerDetails["pluginId"]; + } + + return result; +} + +VectorMapStringString +PluginModel::getPluginPreferences(const QString& path, const QString& accountId) +{ + return PluginManager::instance().getPluginPreferences(path, accountId); +} + +bool +PluginModel::setPluginPreference(const QString& path, + const QString& accountId, + const QString& key, + const QString& value) +{ + auto result = PluginManager::instance().setPluginPreference(path, accountId, key, value); + Q_EMIT modelUpdated(); + return result; +} + +MapStringString +PluginModel::getPluginPreferencesValues(const QString& path, const QString& accountId) +{ + return PluginManager::instance().getPluginPreferencesValues(path, accountId); +} + +bool +PluginModel::resetPluginPreferencesValues(const QString& path, const QString& accountId) +{ + auto result = PluginManager::instance().resetPluginPreferencesValues(path, accountId); + Q_EMIT modelUpdated(); + return result; +} + +} // namespace lrc diff --git a/src/libclient/private/namedirectory_p.h b/src/libclient/private/namedirectory_p.h new file mode 100644 index 0000000000000000000000000000000000000000..85bac9092c28cb459ef9f389f2f6ab175dc066fb --- /dev/null +++ b/src/libclient/private/namedirectory_p.h @@ -0,0 +1,41 @@ +/**************************************************************************** + * Copyright (C) 2016-2022 Savoir-faire Linux Inc. * + * Author : Alexandre Viau <alexandre.viau@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#include "namedirectory.h" + +typedef void (NameDirectoryPrivate::*NameDirectoryPrivateFct)(); + +class NameDirectoryPrivate : public QObject +{ + Q_OBJECT + +private: + NameDirectory* q_ptr; + +public: + NameDirectoryPrivate(NameDirectory*); + +public Q_SLOTS: + void slotNameRegistrationEnded(const QString& accountId, int status, const QString& name); + void slotRegisteredNameFound(const QString& accountId, + int status, + const QString& address, + const QString& name); + void slotExportOnRingEnded(const QString& accountId, int status, const QString& pin); +}; diff --git a/src/libclient/private/smartInfoHub_p.h b/src/libclient/private/smartInfoHub_p.h new file mode 100644 index 0000000000000000000000000000000000000000..83b90c5b1cbb216e6fb7f1f06d7e8488ce896203 --- /dev/null +++ b/src/libclient/private/smartInfoHub_p.h @@ -0,0 +1,51 @@ +/**************************************************************************** + * Copyright (C) 2016-2022 Savoir-faire Linux Inc. * + * Author: Olivier Grégoire <olivier.gregoire@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +/* widget_p.h (_p means private) */ +#include <QObject> +#include "../smartinfohub.h" +#include "typedefs.h" + +#pragma once + +// variables contain in the map information +static QString LOCAL_FPS = QStringLiteral("local FPS"); +static QString LOCAL_AUDIO_CODEC = QStringLiteral("local audio codec"); +static QString LOCAL_VIDEO_CODEC = QStringLiteral("local video codec"); +static QString LOCAL_WIDTH = QStringLiteral("local width"); +static QString LOCAL_HEIGHT = QStringLiteral("local height"); +static QString REMOTE_FPS = QStringLiteral("remote FPS"); +static QString REMOTE_WIDTH = QStringLiteral("remote width"); +static QString REMOTE_HEIGHT = QStringLiteral("remote height"); +static QString REMOTE_VIDEO_CODEC = QStringLiteral("remote video codec"); +static QString REMOTE_AUDIO_CODEC = QStringLiteral("remote audio codec"); +static QString CALL_ID = QStringLiteral("callID"); + +class SmartInfoHubPrivate; +class SmartInfoHubPrivate final : public QObject +{ + Q_OBJECT + +public: + constexpr static const char* DEFAULT_RETURN_VALUE_QSTRING = "void"; + + uint32_t m_refreshTimeInformationMS = 500; + QMap<QString, QString> m_information; + + void setMapInfo(const MapStringString& info); +}; diff --git a/src/libclient/qtwrapper/CMakeLists.txt b/src/libclient/qtwrapper/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..acee0d0cdd3e1b2e5fb0caa6cd2fca7f0832f3aa --- /dev/null +++ b/src/libclient/qtwrapper/CMakeLists.txt @@ -0,0 +1,59 @@ +# Copyright (C) 2015-2022 Savoir-faire Linux Inc. +# +# Author: Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> +# Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com> +# Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> +# Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com> +# Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> +# Author: Amin Bandali <amin.bandali@savoirfairelinux.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +cmake_minimum_required(VERSION 3.16) + +project(qtwrapper) + +message(STATUS "Compiling with ${PROJECT_NAME}") + +if(MUTE_DRING) + # It makes debugging clients easier. + message("Jami daemon/library logs are disabled") + add_definitions(-DMUTE_DRING=true) +endif() + +set(QTWRAPPER_SOURCES + instancemanager.cpp + videomanager_wrap.cpp) + +if(ENABLE_PLUGIN) + message("Adding pluginmanager.cpp") + set(PLUGIN_SOURCES pluginmanager.cpp) +else() + message("Adding pluginmanagerMock.cpp") + set(PLUGIN_SOURCES pluginmanagerMock.cpp) +endif() + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${LIBJAMI_INCLUDE_DIRS}) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../dbus) + +add_library(${PROJECT_NAME} STATIC + ${QTWRAPPER_SOURCES} + ${PLUGIN_SOURCES}) + +target_link_libraries(${PROJECT_NAME} + Qt::Core + ${LIBJAMI_LIB}) diff --git a/src/libclient/qtwrapper/callmanager_wrap.h b/src/libclient/qtwrapper/callmanager_wrap.h new file mode 100644 index 0000000000000000000000000000000000000000..a65a4588bcb38efe784952d926ad71c3054345a2 --- /dev/null +++ b/src/libclient/qtwrapper/callmanager_wrap.h @@ -0,0 +1,614 @@ +/****************************************************************************** + * Copyright (C) 2014-2022 Savoir-faire Linux Inc. * + * Author : Philippe Groarke <philippe.groarke@savoirfairelinux.com> * + * Author : Alexandre Lision <alexandre.lision@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the Lesser GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +#pragma once + +#include <QtCore/QObject> +#include <QtCore/QByteArray> +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QVariant> +#include <QtCore/QTimer> + +#include <callmanager_interface.h> +#include "typedefs.h" +#include "conversions_wrap.hpp" + +/* + * Proxy class for interface cx.ring.Ring.CallManager + */ +class CallManagerInterface : public QObject +{ + Q_OBJECT + +public: + std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> callHandlers; + + CallManagerInterface() + { + using DRing::exportable_callback; + using DRing::CallSignal; + + callHandlers = { + exportable_callback<CallSignal::StateChange>([this](const std::string& accountId, + const std::string& callId, + const std::string& state, + int code) { + LOG_DRING_SIGNAL3("callStateChanged", + QString(callId.c_str()), + QString(state.c_str()), + code); + Q_EMIT callStateChanged(QString(accountId.c_str()), + QString(callId.c_str()), + QString(state.c_str()), + code); + }), + exportable_callback<CallSignal::MediaNegotiationStatus>( + [this](const std::string& callId, + const std::string& event, + const std::vector<std::map<std::string, std::string>>& mediaList) { + LOG_DRING_SIGNAL3("mediaNegotiationStatus", + QString(callId.c_str()), + QString(event.c_str()), + convertVecMap(mediaList)); + Q_EMIT mediaNegotiationStatus(QString(callId.c_str()), + QString(event.c_str()), + convertVecMap(mediaList)); + }), + exportable_callback<CallSignal::TransferFailed>([this]() { + LOG_DRING_SIGNAL("transferFailed", ""); + Q_EMIT transferFailed(); + }), + exportable_callback<CallSignal::TransferSucceeded>([this]() { + LOG_DRING_SIGNAL("transferSucceeded", ""); + Q_EMIT transferSucceeded(); + }), + exportable_callback<CallSignal::RecordPlaybackStopped>( + [this](const std::string& filepath) { + LOG_DRING_SIGNAL("recordPlaybackStopped", QString(filepath.c_str())); + Q_EMIT recordPlaybackStopped(QString(filepath.c_str())); + }), + exportable_callback<CallSignal::VoiceMailNotify>( + [this](const std::string& accountId, int newCount, int oldCount, int urgentCount) { + LOG_DRING_SIGNAL4("voiceMailNotify", + QString(accountId.c_str()), + newCount, + oldCount, + urgentCount); + Q_EMIT voiceMailNotify(QString(accountId.c_str()), + newCount, + oldCount, + urgentCount); + }), + exportable_callback<CallSignal::IncomingMessage>( + [this](const std::string& accountId, + const std::string& callId, + const std::string& from, + const std::map<std::string, std::string>& message) { + LOG_DRING_SIGNAL4("incomingMessage", + QString(accountId.c_str()), + QString(callId.c_str()), + QString(from.c_str()), + convertMap(message)); + Q_EMIT incomingMessage(QString(accountId.c_str()), + QString(callId.c_str()), + QString(from.c_str()), + convertMap(message)); + }), + exportable_callback<CallSignal::IncomingCall>([this](const std::string& accountId, + const std::string& callId, + const std::string& from) { + LOG_DRING_SIGNAL3("incomingCall", + QString(accountId.c_str()), + QString(callId.c_str()), + QString(from.c_str())); + Q_EMIT incomingCall(QString(accountId.c_str()), + QString(callId.c_str()), + QString(from.c_str())); + }), + exportable_callback<CallSignal::IncomingCallWithMedia>( + [this](const std::string& accountId, + const std::string& callId, + const std::string& from, + const std::vector<std::map<std::string, std::string>>& mediaList) { + LOG_DRING_SIGNAL4("incomingCallWithMedia", + QString(accountId.c_str()), + QString(callId.c_str()), + QString(from.c_str()), + convertVecMap(mediaList)); + Q_EMIT incomingCallWithMedia(QString(accountId.c_str()), + QString(callId.c_str()), + QString(from.c_str()), + convertVecMap(mediaList)); + }), + exportable_callback<CallSignal::MediaChangeRequested>( + [this](const std::string& accountId, + const std::string& callId, + const std::vector<std::map<std::string, std::string>>& mediaList) { + LOG_DRING_SIGNAL3("mediaChangeRequested", + QString(accountId.c_str()), + QString(callId.c_str()), + convertVecMap(mediaList)); + Q_EMIT mediaChangeRequested(QString(accountId.c_str()), + QString(callId.c_str()), + convertVecMap(mediaList)); + }), + exportable_callback<CallSignal::RecordPlaybackFilepath>( + [this](const std::string& callId, const std::string& filepath) { + LOG_DRING_SIGNAL2("recordPlaybackFilepath", + QString(callId.c_str()), + QString(filepath.c_str())); + Q_EMIT recordPlaybackFilepath(QString(callId.c_str()), + QString(filepath.c_str())); + }), + exportable_callback<CallSignal::ConferenceCreated>( + [this](const std::string& accountId, const std::string& confId) { + LOG_DRING_SIGNAL2("conferenceCreated", + QString(accountId.c_str()), + QString(confId.c_str())); + Q_EMIT conferenceCreated(QString(accountId.c_str()), QString(confId.c_str())); + }), + exportable_callback<CallSignal::ConferenceChanged>([this](const std::string& accountId, + const std::string& confId, + const std::string& state) { + LOG_DRING_SIGNAL3("conferenceChanged", + QString(accountId.c_str()), + QString(confId.c_str()), + QString(state.c_str())); + Q_EMIT conferenceChanged(QString(accountId.c_str()), + QString(confId.c_str()), + QString(state.c_str())); + }), + exportable_callback<CallSignal::UpdatePlaybackScale>([this](const std::string& filepath, + int position, + int size) { + LOG_DRING_SIGNAL3("updatePlaybackScale", QString(filepath.c_str()), position, size); + Q_EMIT updatePlaybackScale(QString(filepath.c_str()), position, size); + }), + exportable_callback<CallSignal::ConferenceRemoved>( + [this](const std::string& accountId, const std::string& confId) { + LOG_DRING_SIGNAL2("conferenceRemoved", + QString(accountId.c_str()), + QString(confId.c_str())); + Q_EMIT conferenceRemoved(QString(accountId.c_str()), QString(confId.c_str())); + }), + exportable_callback<CallSignal::RecordingStateChanged>([this](const std::string& callId, + bool recordingState) { + LOG_DRING_SIGNAL2("recordingStateChanged", QString(callId.c_str()), recordingState); + Q_EMIT recordingStateChanged(QString(callId.c_str()), recordingState); + }), + exportable_callback<CallSignal::RtcpReportReceived>( + [this](const std::string& callId, const std::map<std::string, int>& report) { + LOG_DRING_SIGNAL2("onRtcpReportReceived", + QString(callId.c_str()), + convertStringInt(report)); + Q_EMIT onRtcpReportReceived(QString(callId.c_str()), convertStringInt(report)); + }), + exportable_callback<CallSignal::OnConferenceInfosUpdated>( + [this](const std::string& confId, + const std::vector<std::map<std::string, std::string>>& infos) { + LOG_DRING_SIGNAL2("onConferenceInfosUpdated", + QString(confId.c_str()), + convertVecMap(infos)); + Q_EMIT onConferenceInfosUpdated(QString(confId.c_str()), convertVecMap(infos)); + }), + exportable_callback<CallSignal::PeerHold>([this](const std::string& callId, bool state) { + LOG_DRING_SIGNAL2("peerHold", QString(callId.c_str()), state); + Q_EMIT peerHold(QString(callId.c_str()), state); + }), + exportable_callback<CallSignal::AudioMuted>( + [this](const std::string& callId, bool state) { + LOG_DRING_SIGNAL2("audioMuted", QString(callId.c_str()), state); + Q_EMIT audioMuted(QString(callId.c_str()), state); + }), + exportable_callback<CallSignal::VideoMuted>( + [this](const std::string& callId, bool state) { + LOG_DRING_SIGNAL2("videoMuted", QString(callId.c_str()), state); + Q_EMIT videoMuted(QString(callId.c_str()), state); + }), + exportable_callback<CallSignal::SmartInfo>( + [this](const std::map<std::string, std::string>& info) { + LOG_DRING_SIGNAL("SmartInfo", ""); + Q_EMIT SmartInfo(convertMap(info)); + }), + exportable_callback<CallSignal::RemoteRecordingChanged>( + [this](const std::string& callId, const std::string& contactId, bool state) { + LOG_DRING_SIGNAL3("remoteRecordingChanged", + QString(callId.c_str()), + QString(contactId.c_str()), + state); + Q_EMIT remoteRecordingChanged(QString(callId.c_str()), + QString(contactId.c_str()), + state); + })}; + } + + ~CallManagerInterface() {} + + bool isValid() { return true; } + +public Q_SLOTS: // METHODS + bool accept(const QString& accountId, const QString& callId) + { + return DRing::accept(accountId.toStdString(), callId.toStdString()); + } + + bool addMainParticipant(const QString& accountId, const QString& confId) + { + return DRing::addMainParticipant(accountId.toStdString(), confId.toStdString()); + } + + bool addParticipant(const QString& accountId, + const QString& callId, + const QString& account2Id, + const QString& confId) + { + return DRing::addParticipant(accountId.toStdString(), + callId.toStdString(), + account2Id.toStdString(), + confId.toStdString()); + } + + bool attendedTransfer(const QString& accountId, + const QString& transferId, + const QString& targetId) + { + return DRing::attendedTransfer(accountId.toStdString(), + transferId.toStdString(), + targetId.toStdString()); + } + + void createConfFromParticipantList(const QString& accountId, const QStringList& participants) + { + DRing::createConfFromParticipantList(accountId.toStdString(), + convertStringList(participants)); + } + + bool detachParticipant(const QString& accountId, const QString& callId) + { + return DRing::detachParticipant(accountId.toStdString(), callId.toStdString()); + } + + MapStringString getCallDetails(const QString& accountId, const QString& callId) + { + MapStringString temp = convertMap( + DRing::getCallDetails(accountId.toStdString(), callId.toStdString())); + return temp; + } + + QStringList getCallList(const QString& accountId) + { + QStringList temp = convertStringList(DRing::getCallList(accountId.toStdString())); + return temp; + } + + MapStringString getConferenceDetails(const QString& accountId, const QString& callId) + { + MapStringString temp = convertMap( + DRing::getConferenceDetails(accountId.toStdString(), callId.toStdString())); + return temp; + } + + VectorMapStringString getConferenceInfos(const QString& accountId, const QString& confId) + { + VectorMapStringString temp = convertVecMap( + DRing::getConferenceInfos(accountId.toStdString(), confId.toStdString())); + return temp; + } + + QString getConferenceId(const QString& accountId, const QString& callId) + { + QString temp(DRing::getConferenceId(accountId.toStdString(), callId.toStdString()).c_str()); + return temp; + } + + QStringList getConferenceList(const QString& accountId) + { + QStringList temp = convertStringList(DRing::getConferenceList(accountId.toStdString())); + return temp; + } + + bool getIsRecording(const QString& accountId, const QString& callId) + { + return DRing::getIsRecording(accountId.toStdString(), callId.toStdString()); + } + + QStringList getParticipantList(const QString& accountId, const QString& confId) + { + QStringList temp = convertStringList( + DRing::getParticipantList(accountId.toStdString(), confId.toStdString())); + return temp; + } + + bool hangUp(const QString& accountId, const QString& callId) + { + return DRing::hangUp(accountId.toStdString(), callId.toStdString()); + } + + bool hangUpConference(const QString& accountId, const QString& confId) + { + return DRing::hangUpConference(accountId.toStdString(), confId.toStdString()); + } + + bool hold(const QString& accountId, const QString& callId) + { + return DRing::hold(accountId.toStdString(), callId.toStdString()); + } + + bool holdConference(const QString& accountId, const QString& confId) + { + return DRing::holdConference(accountId.toStdString(), confId.toStdString()); + } + + bool isConferenceParticipant(const QString& accountId, const QString& callId) + { + return DRing::isConferenceParticipant(accountId.toStdString(), callId.toStdString()); + } + + bool joinConference(const QString& accountId, + const QString& sel_confId, + const QString& account2Id, + const QString& drag_confId) + { + return DRing::joinConference(accountId.toStdString(), + sel_confId.toStdString(), + account2Id.toStdString(), + drag_confId.toStdString()); + } + + bool joinParticipant(const QString& accountId, + const QString& sel_callId, + const QString& account2Id, + const QString& drag_callId) + { + return DRing::joinParticipant(accountId.toStdString(), + sel_callId.toStdString(), + account2Id.toStdString(), + drag_callId.toStdString()); + } + + QString placeCall(const QString& accountId, const QString& to) + { + QString temp(DRing::placeCall(accountId.toStdString(), to.toStdString()).c_str()); + return temp; + } + + // MULTISTREAM FUNCTIONS + QString placeCallWithMedia(const QString& accountId, + const QString& to, + const VectorMapStringString& mediaList) + { + QString temp(DRing::placeCallWithMedia(accountId.toStdString(), + to.toStdString(), + convertVecMap(mediaList)) + .c_str()); + return temp; + } + + bool requestMediaChange(const QString& accountId, + const QString& callId, + const VectorMapStringString& mediaList) + { + return DRing::requestMediaChange(accountId.toStdString(), + callId.toStdString(), + convertVecMap(mediaList)); + } + + bool acceptWithMedia(const QString& accountId, + const QString& callId, + const VectorMapStringString& mediaList) + { + return DRing::acceptWithMedia(accountId.toStdString(), + callId.toStdString(), + convertVecMap(mediaList)); + } + + bool answerMediaChangeRequest(const QString& accountId, + const QString& callId, + const VectorMapStringString& mediaList) + { + return DRing::answerMediaChangeRequest(accountId.toStdString(), + callId.toStdString(), + convertVecMap(mediaList)); + } + // END OF MULTISTREAM FUNCTIONS + + void playDTMF(const QString& key) { DRing::playDTMF(key.toStdString()); } + + void recordPlaybackSeek(double value) { DRing::recordPlaybackSeek(value); } + + bool refuse(const QString& accountId, const QString& callId) + { + return DRing::refuse(accountId.toStdString(), callId.toStdString()); + } + + void sendTextMessage(const QString& accountId, + const QString& callId, + const QMap<QString, QString>& message, + bool isMixed) + { + DRing::sendTextMessage(accountId.toStdString(), + callId.toStdString(), + convertMap(message), + QObject::tr("Me").toStdString(), + isMixed); + } + + bool startRecordedFilePlayback(const QString& filepath) + { + // TODO: Change method name to match API + return DRing::startRecordedFilePlayback(filepath.toStdString()); + } + + void startTone(int start, int type) { DRing::startTone(start, type); } + + void stopRecordedFilePlayback() { DRing::stopRecordedFilePlayback(); } + + bool toggleRecording(const QString& accountId, const QString& callId) + { + return DRing::toggleRecording(accountId.toStdString(), callId.toStdString()); + } + + bool transfer(const QString& accountId, const QString& callId, const QString& to) + { + return DRing::transfer(accountId.toStdString(), callId.toStdString(), to.toStdString()); + } + + bool unhold(const QString& accountId, const QString& callId) + { + return DRing::unhold(accountId.toStdString(), callId.toStdString()); + } + + bool unholdConference(const QString& accountId, const QString& confId) + { + return DRing::unholdConference(accountId.toStdString(), confId.toStdString()); + } + + bool muteLocalMedia(const QString& accountId, + const QString& callId, + const QString& mediaType, + bool mute) + { + return DRing::muteLocalMedia(accountId.toStdString(), + callId.toStdString(), + mediaType.toStdString(), + mute); + } + + void startSmartInfo(int refresh) { DRing::startSmartInfo(refresh); } + + void stopSmartInfo() { DRing::stopSmartInfo(); } + + void setConferenceLayout(const QString& accountId, const QString& confId, int layout) + { + DRing::setConferenceLayout(accountId.toStdString(), confId.toStdString(), layout); + } + + void setActiveParticipant(const QString& accountId, const QString& confId, const QString& callId) + { + DRing::setActiveParticipant(accountId.toStdString(), + confId.toStdString(), + callId.toStdString()); + } + + bool switchInput(const QString& accountId, const QString& callId, const QString& resource) + { +#ifdef ENABLE_VIDEO + return DRing::switchInput(accountId.toStdString(), + callId.toStdString(), + resource.toStdString()); +#else + Q_UNUSED(accountId) + Q_UNUSED(callId) + Q_UNUSED(resource) + return false; +#endif + } + + void setModerator(const QString& accountId, + const QString& confId, + const QString& peerId, + const bool& state) + { + DRing::setModerator(accountId.toStdString(), + confId.toStdString(), + peerId.toStdString(), + state); + } + + void muteParticipant(const QString& accountId, + const QString& confId, + const QString& peerId, + const bool& state) + { + DRing::muteParticipant(accountId.toStdString(), + confId.toStdString(), + peerId.toStdString(), + state); + } + + void hangupParticipant(const QString& accountId, + const QString& confId, + const QString& participant) + { + DRing::hangupParticipant(accountId.toStdString(), + confId.toStdString(), + participant.toStdString()); + } + + void raiseParticipantHand(const QString& accountId, + const QString& confId, + const QString& peerId, + const bool& state) + { + DRing::raiseParticipantHand(accountId.toStdString(), + confId.toStdString(), + peerId.toStdString(), + state); + } + +Q_SIGNALS: // SIGNALS + void callStateChanged(const QString& accountId, + const QString& callId, + const QString& state, + int code); + void mediaNegotiationStatus(const QString& callId, + const QString& event, + const VectorMapStringString& mediaList); + void transferFailed(); + void transferSucceeded(); + void recordPlaybackStopped(const QString& filepath); + void voiceMailNotify(const QString& accountId, int newCount, int oldCount, int urgentCount); + void incomingMessage(const QString& accountId, + const QString& callId, + const QString& from, + const MapStringString& message); + void incomingCall(const QString& accountId, const QString& callId, const QString& from); + void incomingCallWithMedia(const QString& accountId, + const QString& callId, + const QString& from, + const VectorMapStringString& mediaList); + void mediaChangeRequested(const QString& accountId, + const QString& callId, + const VectorMapStringString& mediaList); + void recordPlaybackFilepath(const QString& callId, const QString& filepath); + void conferenceCreated(const QString& accountId, const QString& confId); + void conferenceChanged(const QString& accountId, const QString& confId, const QString& state); + void updatePlaybackScale(const QString& filepath, int position, int size); + void conferenceRemoved(const QString& accountId, const QString& confId); + void recordingStateChanged(const QString& callId, bool recordingState); + void onRtcpReportReceived(const QString& callId, MapStringInt report); + void onConferenceInfosUpdated(const QString& confId, VectorMapStringString infos); + void audioMuted(const QString& callId, bool state); + void videoMuted(const QString& callId, bool state); + void peerHold(const QString& callId, bool state); + void SmartInfo(const MapStringString& info); + void remoteRecordingChanged(const QString& callId, + const QString& peerNumber, + bool remoteRecordingState); +}; + +namespace org { +namespace ring { +namespace Ring { +typedef ::CallManagerInterface CallManager; +} +} // namespace ring +} // namespace org diff --git a/src/libclient/qtwrapper/configurationmanager_wrap.h b/src/libclient/qtwrapper/configurationmanager_wrap.h new file mode 100644 index 0000000000000000000000000000000000000000..2807f8ab2b86414091af300a016580ee5f400803 --- /dev/null +++ b/src/libclient/qtwrapper/configurationmanager_wrap.h @@ -0,0 +1,1147 @@ +/****************************************************************************** + * Copyright (C) 2014-2022 Savoir-faire Linux Inc. * + * Author : Philippe Groarke <philippe.groarke@savoirfairelinux.com> * + * Author : Alexandre Lision <alexandre.lision@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the Lesser GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +#pragma once + +#include <QtCore/QObject> +#include <QtCore/QByteArray> +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtCore/QTimer> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QVariant> + +#include <future> + +#include <configurationmanager_interface.h> +#include <datatransfer_interface.h> +#include <account_const.h> +#include <conversation_interface.h> + +#include "typedefs.h" +#include "conversions_wrap.hpp" + +/* + * Proxy class for interface org.ring.Ring.ConfigurationManager + */ +class ConfigurationManagerInterface : public QObject +{ + Q_OBJECT + +public: + std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> confHandlers; + std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> dataXferHandlers; + std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> conversationsHandlers; + + ConfigurationManagerInterface() + { + setObjectName("ConfigurationManagerInterface"); + using DRing::exportable_callback; + using DRing::ConfigurationSignal; + using DRing::AudioSignal; + using DRing::DataTransferSignal; + using DRing::ConversationSignal; + + setObjectName("ConfigurationManagerInterface"); + confHandlers = { + exportable_callback<ConfigurationSignal::VolumeChanged>( + [this](const std::string& device, double value) { + Q_EMIT this->volumeChanged(QString(device.c_str()), value); + }), + exportable_callback<ConfigurationSignal::AccountsChanged>( + [this]() { Q_EMIT this->accountsChanged(); }), + exportable_callback<ConfigurationSignal::AccountDetailsChanged>( + [this](const std::string& account_id, + const std::map<std::string, std::string>& details) { + Q_EMIT this->accountDetailsChanged(QString(account_id.c_str()), + convertMap(details)); + }), + exportable_callback<ConfigurationSignal::StunStatusFailed>( + [this](const std::string& reason) { + Q_EMIT this->stunStatusFailure(QString(reason.c_str())); + }), + exportable_callback<ConfigurationSignal::RegistrationStateChanged>( + [this](const std::string& accountID, + const std::string& registration_state, + unsigned detail_code, + const std::string& detail_str) { + Q_EMIT this->registrationStateChanged(QString(accountID.c_str()), + QString(registration_state.c_str()), + detail_code, + QString(detail_str.c_str())); + }), + exportable_callback<ConfigurationSignal::VolatileDetailsChanged>( + [this](const std::string& accountID, + const std::map<std::string, std::string>& details) { + Q_EMIT this->volatileAccountDetailsChanged(QString(accountID.c_str()), + convertMap(details)); + }), + exportable_callback<ConfigurationSignal::Error>( + [this](int code) { Q_EMIT this->errorAlert(code); }), + exportable_callback<ConfigurationSignal::CertificateExpired>( + [this](const std::string& certId) { + Q_EMIT this->certificateExpired(QString(certId.c_str())); + }), + exportable_callback<ConfigurationSignal::CertificatePinned>( + [this](const std::string& certId) { + Q_EMIT this->certificatePinned(QString(certId.c_str())); + }), + exportable_callback<ConfigurationSignal::CertificatePathPinned>( + [this](const std::string& certPath, const std::vector<std::string>& list) { + Q_EMIT this->certificatePathPinned(QString(certPath.c_str()), + convertStringList(list)); + }), + exportable_callback<ConfigurationSignal::CertificateStateChanged>( + [this](const std::string& accountID, + const std::string& certId, + const std::string& state) { + QTimer::singleShot(0, [this, accountID, certId, state] { + Q_EMIT this->certificateStateChanged(QString(accountID.c_str()), + QString(certId.c_str()), + QString(state.c_str())); + }); + }), + exportable_callback<DRing::ConfigurationSignal::AccountMessageStatusChanged>( + [this](const std::string& account_id, + const std::string& conversation_id, + const std::string& peer, + const std::string message_id, + int state) { + Q_EMIT this->accountMessageStatusChanged(QString(account_id.c_str()), + QString(conversation_id.c_str()), + QString(peer.c_str()), + QString(message_id.c_str()), + state); + }), + exportable_callback<ConfigurationSignal::IncomingTrustRequest>( + [this](const std::string& accountId, + const std::string& conversationId, + const std::string& certId, + const std::vector<uint8_t>& payload, + time_t timestamp) { + Q_EMIT this->incomingTrustRequest(QString(accountId.c_str()), + QString(conversationId.c_str()), + QString(certId.c_str()), + QByteArray(reinterpret_cast<const char*>( + payload.data()), + payload.size()), + timestamp); + }), + exportable_callback<ConfigurationSignal::KnownDevicesChanged>( + [this](const std::string& accountId, + const std::map<std::string, std::string>& devices) { + Q_EMIT this->knownDevicesChanged(QString(accountId.c_str()), + convertMap(devices)); + }), + exportable_callback<ConfigurationSignal::DeviceRevocationEnded>( + [this](const std::string& accountId, const std::string& device, int status) { + Q_EMIT this->deviceRevocationEnded(QString(accountId.c_str()), + QString(device.c_str()), + status); + }), + exportable_callback<ConfigurationSignal::AccountProfileReceived>( + [this](const std::string& accountId, + const std::string& displayName, + const std::string& userPhoto) { + Q_EMIT this->accountProfileReceived(QString(accountId.c_str()), + QString(displayName.c_str()), + QString(userPhoto.c_str())); + }), + exportable_callback<ConfigurationSignal::ExportOnRingEnded>( + [this](const std::string& accountId, int status, const std::string& pin) { + Q_EMIT this->exportOnRingEnded(QString(accountId.c_str()), + status, + QString(pin.c_str())); + }), + exportable_callback<ConfigurationSignal::NameRegistrationEnded>( + [this](const std::string& accountId, int status, const std::string& name) { + Q_EMIT this->nameRegistrationEnded(QString(accountId.c_str()), + status, + QString(name.c_str())); + }), + exportable_callback<ConfigurationSignal::RegisteredNameFound>( + [this](const std::string& accountId, + int status, + const std::string& address, + const std::string& name) { + Q_EMIT this->registeredNameFound(QString(accountId.c_str()), + status, + QString(address.c_str()), + QString(name.c_str())); + }), + exportable_callback<ConfigurationSignal::IncomingAccountMessage>( + [this](const std::string& account_id, + const std::string& from, + const std::string& msgId, + const std::map<std::string, std::string>& payloads) { + Q_EMIT this->incomingAccountMessage(QString(account_id.c_str()), + QString(from.c_str()), + QString(msgId.c_str()), + convertMap(payloads)); + }), + exportable_callback<ConfigurationSignal::MediaParametersChanged>( + [this](const std::string& account_id) { + Q_EMIT this->mediaParametersChanged(QString(account_id.c_str())); + }), + exportable_callback<AudioSignal::DeviceEvent>( + [this]() { Q_EMIT this->audioDeviceEvent(); }), + exportable_callback<AudioSignal::AudioMeter>([this](const std::string& id, float level) { + Q_EMIT this->audioMeter(QString(id.c_str()), level); + }), + exportable_callback<ConfigurationSignal::MigrationEnded>( + [this](const std::string& account_id, const std::string& result) { + Q_EMIT this->migrationEnded(QString(account_id.c_str()), + QString(result.c_str())); + }), + exportable_callback<ConfigurationSignal::ContactAdded>( + [this](const std::string& account_id, const std::string& uri, const bool& confirmed) { + Q_EMIT this->contactAdded(QString(account_id.c_str()), + QString(uri.c_str()), + confirmed); + }), + exportable_callback<ConfigurationSignal::ProfileReceived>( + [this](const std::string& accountID, + const std::string& peer, + const std::string& vCard) { + Q_EMIT this->profileReceived(QString(accountID.c_str()), + QString(peer.c_str()), + QString(vCard.c_str())); + }), + exportable_callback<ConfigurationSignal::ContactRemoved>( + [this](const std::string& account_id, const std::string& uri, const bool& banned) { + Q_EMIT this->contactRemoved(QString(account_id.c_str()), + QString(uri.c_str()), + banned); + }), + exportable_callback<ConfigurationSignal::MessageSend>( + [this](const std::string& message) { + Q_EMIT this->messageSend(QString(message.c_str())); + }), + exportable_callback<ConfigurationSignal::ComposingStatusChanged>( + [this](const std::string& account_id, + const std::string& convId, + const std::string& from, + int status) { + Q_EMIT this->composingStatusChanged(QString(account_id.c_str()), + QString(convId.c_str()), + QString(from.c_str()), + status > 0 ? true : false); + }), + exportable_callback<ConfigurationSignal::UserSearchEnded>( + [this](const std::string& account_id, + int status, + const std::string& query, + const std::vector<std::map<std::string, std::string>>& results) { + Q_EMIT this->userSearchEnded(QString(account_id.c_str()), + status, + QString(query.c_str()), + convertVecMap(results)); + }), + }; + + dataXferHandlers = { + exportable_callback<DataTransferSignal::DataTransferEvent>( + [this](const std::string& accountId, + const std::string& conversationId, + const std::string& interactionId, + const std::string& fileId, + const uint32_t& code) { + Q_EMIT this->dataTransferEvent(QString(accountId.c_str()), + QString(conversationId.c_str()), + QString(interactionId.c_str()), + QString(fileId.c_str()), + code); + }), + }; + conversationsHandlers + = {exportable_callback<ConversationSignal::ConversationLoaded>( + [this](uint32_t id, + const std::string& accountId, + const std::string& conversationId, + const std::vector<std::map<std::string, std::string>>& messages) { + Q_EMIT conversationLoaded(id, + QString(accountId.c_str()), + QString(conversationId.c_str()), + convertVecMap(messages)); + }), + exportable_callback<ConversationSignal::MessageReceived>( + [this](const std::string& accountId, + const std::string& conversationId, + const std::map<std::string, std::string>& message) { + Q_EMIT messageReceived(QString(accountId.c_str()), + QString(conversationId.c_str()), + convertMap(message)); + }), + exportable_callback<ConversationSignal::ConversationRequestReceived>( + [this](const std::string& accountId, + const std::string& conversationId, + const std::map<std::string, std::string>& metadata) { + Q_EMIT conversationRequestReceived(QString(accountId.c_str()), + QString(conversationId.c_str()), + convertMap(metadata)); + }), + exportable_callback<ConversationSignal::ConversationRequestDeclined>( + [this](const std::string& accountId, const std::string& conversationId) { + Q_EMIT conversationRequestDeclined(QString(accountId.c_str()), + QString(conversationId.c_str())); + }), + exportable_callback<ConversationSignal::ConversationReady>( + [this](const std::string& accountId, const std::string& conversationId) { + Q_EMIT conversationReady(QString(accountId.c_str()), + QString(conversationId.c_str())); + }), + exportable_callback<ConversationSignal::ConversationRemoved>( + [this](const std::string& accountId, const std::string& conversationId) { + Q_EMIT conversationRemoved(QString(accountId.c_str()), + QString(conversationId.c_str())); + }), + exportable_callback<ConversationSignal::ConversationMemberEvent>( + [this](const std::string& accountId, + const std::string& conversationId, + const std::string& memberId, + int event) { + Q_EMIT conversationMemberEvent(QString(accountId.c_str()), + QString(conversationId.c_str()), + QString(memberId.c_str()), + event); + })}; + } + + ~ConfigurationManagerInterface() {} + +public Q_SLOTS: // METHODS + QString addAccount(MapStringString details) + { + QString temp(DRing::addAccount(convertMap(details)).c_str()); + return temp; + } + + void downloadFile(const QString& accountId, + const QString& convId, + const QString& interactionId, + const QString& fileId, + const QString& path) + { + DRing::downloadFile(accountId.toStdString(), + convId.toStdString(), + interactionId.toStdString(), + fileId.toStdString(), + path.toStdString()); + } + + bool exportOnRing(const QString& accountID, const QString& password) + { + return DRing::exportOnRing(accountID.toStdString(), password.toStdString()); + } + + bool exportToFile(const QString& accountID, + const QString& destinationPath, + const QString& password = {}) + { + return DRing::exportToFile(accountID.toStdString(), + destinationPath.toStdString(), + password.toStdString()); + } + + MapStringString getKnownRingDevices(const QString& accountID) + { + MapStringString temp = convertMap(DRing::getKnownRingDevices(accountID.toStdString())); + return temp; + } + + bool lookupName(const QString& accountID, const QString& nameServiceURL, const QString& name) + { + return DRing::lookupName(accountID.toStdString(), + nameServiceURL.toStdString(), + name.toStdString()); + } + + bool lookupAddress(const QString& accountID, + const QString& nameServiceURL, + const QString& address) + { + return DRing::lookupAddress(accountID.toStdString(), + nameServiceURL.toStdString(), + address.toStdString()); + } + + bool registerName(const QString& accountID, const QString& password, const QString& name) + { + return DRing::registerName(accountID.toStdString(), + password.toStdString(), + name.toStdString()); + } + + MapStringString getAccountDetails(const QString& accountID) + { + MapStringString temp = convertMap(DRing::getAccountDetails(accountID.toStdString())); + return temp; + } + + QStringList getAccountList() + { + QStringList temp = convertStringList(DRing::getAccountList()); + return temp; + } + + MapStringString getAccountTemplate(const QString& accountType) + { + MapStringString temp = convertMap(DRing::getAccountTemplate(accountType.toStdString())); + return temp; + } + + // TODO: works? + VectorUInt getActiveCodecList(const QString& accountId) + { + std::vector<unsigned int> v = DRing::getActiveCodecList(accountId.toStdString()); + return QVector<unsigned int>(v.begin(), v.end()); + } + + QString getAddrFromInterfaceName(const QString& interface) + { + QString temp(DRing::getAddrFromInterfaceName(interface.toStdString()).c_str()); + return temp; + } + + QStringList getAllIpInterface() + { + QStringList temp = convertStringList(DRing::getAllIpInterface()); + return temp; + } + + QStringList getAllIpInterfaceByName() + { + QStringList temp = convertStringList(DRing::getAllIpInterfaceByName()); + return temp; + } + + MapStringString getCodecDetails(const QString& accountID, int payload) + { + MapStringString temp = convertMap( + DRing::getCodecDetails(accountID.toStdString().c_str(), payload)); + return temp; + } + + VectorUInt getCodecList() + { + std::vector<unsigned int> v = DRing::getCodecList(); + return QVector<unsigned int>(v.begin(), v.end()); + } + + VectorMapStringString getContacts(const QString& accountID) + { + VectorMapStringString temp; + for (const auto& x : DRing::getContacts(accountID.toStdString())) { + temp.push_back(convertMap(x)); + } + return temp; + } + + int getAudioInputDeviceIndex(const QString& devname) + { + return DRing::getAudioInputDeviceIndex(devname.toStdString()); + } + + QStringList getAudioInputDeviceList() + { + QStringList temp = convertStringList(DRing::getAudioInputDeviceList()); + return temp; + } + + QString getAudioManager() + { + QString temp(DRing::getAudioManager().c_str()); + return temp; + } + + int getAudioOutputDeviceIndex(const QString& devname) + { + return DRing::getAudioOutputDeviceIndex(devname.toStdString()); + } + + QStringList getAudioOutputDeviceList() + { + QStringList temp = convertStringList(DRing::getAudioOutputDeviceList()); + return temp; + } + + QStringList getAudioPluginList() + { + QStringList temp = convertStringList(DRing::getAudioPluginList()); + return temp; + } + + VectorMapStringString getCredentials(const QString& accountID) + { + VectorMapStringString temp; + for (auto x : DRing::getCredentials(accountID.toStdString())) { + temp.push_back(convertMap(x)); + } + return temp; + } + + QStringList getCurrentAudioDevicesIndex() + { + QStringList temp = convertStringList(DRing::getCurrentAudioDevicesIndex()); + return temp; + } + + QString getCurrentAudioOutputPlugin() + { + QString temp(DRing::getCurrentAudioOutputPlugin().c_str()); + return temp; + } + + int getHistoryLimit() { return DRing::getHistoryLimit(); } + + bool getIsAlwaysRecording() { return DRing::getIsAlwaysRecording(); } + + bool getNoiseSuppressState() { return DRing::getNoiseSuppressState(); } + + QString getRecordPath() + { + QString temp(DRing::getRecordPath().c_str()); + return temp; + } + + bool getRecordPreview() { return DRing::getRecordPreview(); } + + int getRecordQuality() { return DRing::getRecordQuality(); } + + QStringList getSupportedAudioManagers() + { + return convertStringList(DRing::getSupportedAudioManagers()); + } + + QStringList getSupportedTlsMethod() + { + QStringList temp = convertStringList(DRing::getSupportedTlsMethod()); + return temp; + } + + MapStringString validateCertificate(const QString& unused, const QString& certificate) + { + MapStringString temp = convertMap( + DRing::validateCertificate(unused.toStdString(), certificate.toStdString())); + return temp; + } + + MapStringString validateCertificatePath(const QString& unused, + const QString& certificate, + const QString& privateKey, + const QString& privateKeyPass, + const QString& caListPath) + { + MapStringString temp = convertMap( + DRing::validateCertificatePath(unused.toStdString(), + certificate.toStdString(), + privateKey.toStdString(), + privateKeyPass.toStdString(), + caListPath.toStdString())); + return temp; + } + + MapStringString getCertificateDetails(const QString& certificate) + { + MapStringString temp = convertMap(DRing::getCertificateDetails(certificate.toStdString())); + return temp; + } + + MapStringString getCertificateDetailsPath(const QString& certificate, + const QString& privateKey, + const QString& privateKeyPass) + { + MapStringString temp = convertMap( + DRing::getCertificateDetailsPath(certificate.toStdString(), + privateKey.toStdString(), + privateKeyPass.toStdString())); + return temp; + } + + QStringList getSupportedCiphers(const QString& accountID) + { + QStringList temp = convertStringList(DRing::getSupportedCiphers(accountID.toStdString())); + return temp; + } + + double getVolume(const QString& device) { return DRing::getVolume(device.toStdString()); } + + bool isAgcEnabled() { return DRing::isAgcEnabled(); } + + bool isCaptureMuted() { return DRing::isCaptureMuted(); } + + bool isDtmfMuted() { return DRing::isDtmfMuted(); } + + bool isPlaybackMuted() { return DRing::isPlaybackMuted(); } + + void muteCapture(bool mute) { DRing::muteCapture(mute); } + + void muteDtmf(bool mute) { DRing::muteDtmf(mute); } + + void mutePlayback(bool mute) { DRing::mutePlayback(mute); } + + void registerAllAccounts() { DRing::registerAllAccounts(); } + + void monitor(bool continuous) { DRing::monitor(continuous); } + + void removeAccount(const QString& accountID) { DRing::removeAccount(accountID.toStdString()); } + + bool changeAccountPassword(const QString& id, + const QString& currentPassword, + const QString& newPassword) + { + return DRing::changeAccountPassword(id.toStdString(), + currentPassword.toStdString(), + newPassword.toStdString()); + } + + void sendRegister(const QString& accountID, bool enable) + { + DRing::sendRegister(accountID.toStdString(), enable); + } + + void setAccountDetails(const QString& accountID, MapStringString details) + { + DRing::setAccountDetails(accountID.toStdString(), convertMap(details)); + } + + void setAccountsOrder(const QString& order) { DRing::setAccountsOrder(order.toStdString()); } + + void setActiveCodecList(const QString& accountID, VectorUInt& list) + { + // const std::vector<unsigned int> converted = convertStringList(list); + DRing::setActiveCodecList(accountID.toStdString(), + std::vector<unsigned>(list.begin(), list.end())); + } + + void setAgcState(bool enabled) { DRing::setAgcState(enabled); } + + void setAudioInputDevice(int index) { DRing::setAudioInputDevice(index); } + + bool setAudioManager(const QString& api) { return DRing::setAudioManager(api.toStdString()); } + + void setAudioOutputDevice(int index) { DRing::setAudioOutputDevice(index); } + + void setAudioPlugin(const QString& audioPlugin) + { + DRing::setAudioPlugin(audioPlugin.toStdString()); + } + + void setAudioRingtoneDevice(int index) { DRing::setAudioRingtoneDevice(index); } + + void setCredentials(const QString& accountID, VectorMapStringString credentialInformation) + { + std::vector<std::map<std::string, std::string>> temp; + for (auto x : credentialInformation) { + temp.push_back(convertMap(x)); + } + DRing::setCredentials(accountID.toStdString(), temp); + } + + void setHistoryLimit(int days) { DRing::setHistoryLimit(days); } + + void setIsAlwaysRecording(bool enabled) { DRing::setIsAlwaysRecording(enabled); } + + void setNoiseSuppressState(bool state) { DRing::setNoiseSuppressState(state); } + + bool isAudioMeterActive(const QString& id) + { + return DRing::isAudioMeterActive(id.toStdString()); + } + + void setAudioMeterState(const QString& id, bool state) + { + DRing::setAudioMeterState(id.toStdString(), state); + } + + void setRecordPath(const QString& rec) { DRing::setRecordPath(rec.toStdString()); } + + void setRecordPreview(const bool& rec) { DRing::setRecordPreview(rec); } + + void setRecordQuality(const int& quality) { DRing::setRecordQuality(quality); } + + void setVolume(const QString& device, double value) + { + DRing::setVolume(device.toStdString(), value); + } + + MapStringString getVolatileAccountDetails(const QString& accountID) + { + MapStringString temp = convertMap(DRing::getVolatileAccountDetails(accountID.toStdString())); + return temp; + } + + QStringList getPinnedCertificates() + { + QStringList temp = convertStringList(DRing::getPinnedCertificates()); + return temp; + } + + QStringList pinCertificate(const QByteArray& content, bool local) + { + std::vector<unsigned char> raw(content.begin(), content.end()); + return convertStringList(DRing::pinCertificate(raw, local)); + } + + bool unpinCertificate(const QString& certId) + { + return DRing::unpinCertificate(certId.toStdString()); + } + + void pinCertificatePath(const QString& certPath) + { + DRing::pinCertificatePath(certPath.toStdString()); + } + + uint unpinCertificatePath(const QString& certPath) + { + return DRing::unpinCertificatePath(certPath.toStdString()); + } + + bool pinRemoteCertificate(const QString& accountId, const QString& certPath) + { + return DRing::pinRemoteCertificate(accountId.toStdString(), certPath.toStdString()); + } + + bool setCertificateStatus(const QString& accountId, + const QString& certPath, + const QString& status) + { + return DRing::setCertificateStatus(accountId.toStdString(), + certPath.toStdString(), + status.toStdString()); + } + + QStringList getCertificatesByStatus(const QString& accountId, const QString& status) + { + return convertStringList( + DRing::getCertificatesByStatus(accountId.toStdString(), status.toStdString())); + } + + VectorMapStringString getTrustRequests(const QString& accountId) + { + return convertVecMap(DRing::getTrustRequests(accountId.toStdString())); + } + + bool acceptTrustRequest(const QString& accountId, const QString& from) + { + return DRing::acceptTrustRequest(accountId.toStdString(), from.toStdString()); + } + + bool discardTrustRequest(const QString& accountId, const QString& from) + { + return DRing::discardTrustRequest(accountId.toStdString(), from.toStdString()); + } + + void sendTrustRequest(const QString& accountId, const QString& from, const QByteArray& payload) + { + std::vector<unsigned char> raw(payload.begin(), payload.end()); + DRing::sendTrustRequest(accountId.toStdString(), from.toStdString(), raw); + } + + void removeContact(const QString& accountId, const QString& uri, bool ban) + { + DRing::removeContact(accountId.toStdString(), uri.toStdString(), ban); + } + + void revokeDevice(const QString& accountId, const QString& password, const QString& deviceId) + { + DRing::revokeDevice(accountId.toStdString(), password.toStdString(), deviceId.toStdString()); + } + + void addContact(const QString& accountId, const QString& uri) + { + DRing::addContact(accountId.toStdString(), uri.toStdString()); + } + + uint64_t sendTextMessage(const QString& accountId, + const QString& to, + const QMap<QString, QString>& payloads) + { + return DRing::sendAccountTextMessage(accountId.toStdString(), + to.toStdString(), + convertMap(payloads)); + } + + QVector<Message> getLastMessages(const QString& accountID, const uint64_t& base_timestamp) + { + QVector<Message> result; + for (auto& message : DRing::getLastMessages(accountID.toStdString(), base_timestamp)) { + result.append({message.from.c_str(), convertMap(message.payloads), message.received}); + } + return result; + } + + bool setCodecDetails(const QString& accountId, + unsigned int codecId, + const MapStringString& details) + { + return DRing::setCodecDetails(accountId.toStdString(), codecId, convertMap(details)); + } + + int getMessageStatus(uint64_t id) { return DRing::getMessageStatus(id); } + + MapStringString getNearbyPeers(const QString& accountID) + { + return convertMap(DRing::getNearbyPeers(accountID.toStdString())); + } + + void connectivityChanged() { DRing::connectivityChanged(); } + + MapStringString getContactDetails(const QString& accountID, const QString& uri) + { + return convertMap(DRing::getContactDetails(accountID.toStdString(), uri.toStdString())); + } + + uint32_t sendFileLegacy(const DataTransferInfo& lrc_info, DRing::DataTransferId& id) + { + DRing::DataTransferInfo transfer_info; + transfer_info.accountId = lrc_info.accountId.toStdString(); + transfer_info.lastEvent = decltype(transfer_info.lastEvent)(lrc_info.lastEvent); + transfer_info.flags = lrc_info.flags; + transfer_info.totalSize = lrc_info.totalSize; + transfer_info.bytesProgress = lrc_info.bytesProgress; + transfer_info.peer = lrc_info.peer.toStdString(); + transfer_info.conversationId = lrc_info.conversationId.toStdString(); + transfer_info.displayName = lrc_info.displayName.toStdString(); + transfer_info.path = lrc_info.path.toStdString(); + transfer_info.mimetype = lrc_info.mimetype.toStdString(); + return uint32_t(DRing::sendFileLegacy(transfer_info, id)); + } + + void sendFile(const QString& accountId, + const QString& conversationId, + const QString& filePath, + const QString& fileDisplayName, + const QString& parent) + { + DRing::sendFile(accountId.toStdString(), + conversationId.toStdString(), + filePath.toStdString(), + fileDisplayName.toStdString(), + parent.toStdString()); + } + + uint32_t dataTransferInfo(QString accountId, QString transfer_id, DataTransferInfo& lrc_info) + { + DRing::DataTransferInfo transfer_info; + auto error = uint32_t(DRing::dataTransferInfo(accountId.toStdString(), + transfer_id.toStdString(), + transfer_info)); + lrc_info.accountId = QString::fromStdString(transfer_info.accountId); + lrc_info.lastEvent = quint32(transfer_info.lastEvent); + lrc_info.flags = transfer_info.flags; + lrc_info.totalSize = transfer_info.totalSize; + lrc_info.bytesProgress = transfer_info.bytesProgress; + lrc_info.peer = QString::fromStdString(transfer_info.peer); + lrc_info.conversationId = QString::fromStdString(transfer_info.conversationId); + lrc_info.displayName = QString::fromStdString(transfer_info.displayName); + lrc_info.path = QString::fromStdString(transfer_info.path); + lrc_info.mimetype = QString::fromStdString(transfer_info.mimetype); + return error; + } + + uint64_t fileTransferInfo(QString accountId, + QString conversationId, + QString fileId, + QString& path, + qlonglong& total, + qlonglong& progress) + { + std::string pathstr; + auto result = uint32_t(DRing::fileTransferInfo(accountId.toStdString(), + conversationId.toStdString(), + fileId.toStdString(), + pathstr, + reinterpret_cast<int64_t&>(total), + reinterpret_cast<int64_t&>(progress))); + path = pathstr.c_str(); + return result; + } + + uint32_t acceptFileTransfer(QString accountId, const QString& fileId, const QString& file_path) + { + return uint32_t(DRing::acceptFileTransfer(accountId.toStdString(), + fileId.toStdString(), + file_path.toStdString())); + } + + uint32_t cancelDataTransfer(QString accountId, QString conversationId, QString transfer_id) + { + return uint32_t(DRing::cancelDataTransfer(accountId.toStdString(), + conversationId.toStdString(), + transfer_id.toStdString())); + } + + void enableProxyClient(const QString& accountID, bool enable) + { + DRing::enableProxyClient(accountID.toStdString(), enable); + } + + void setPushNotificationToken(const QString& token) + { + DRing::setPushNotificationToken(token.toStdString()); + } + + void pushNotificationReceived(const QString& from, const MapStringString& data) + { + DRing::pushNotificationReceived(from.toStdString(), convertMap(data)); + } + + void setIsComposing(const QString& accountId, const QString& contactId, bool isComposing) + { + DRing::setIsComposing(accountId.toStdString(), contactId.toStdString(), isComposing); + } + + bool setMessageDisplayed(const QString& accountId, + const QString& contactId, + const QString& messageId, + int status) + { + return DRing::setMessageDisplayed(accountId.toStdString(), + contactId.toStdString(), + messageId.toStdString(), + status); + } + + bool searchUser(const QString& accountId, const QString& query) + { + return DRing::searchUser(accountId.toStdString(), query.toStdString()); + } + // swarm + QString startConversation(const QString& accountId) + { + auto convId = DRing::startConversation(accountId.toStdString()); + return QString(convId.c_str()); + } + void acceptConversationRequest(const QString& accountId, const QString& conversationId) + { + DRing::acceptConversationRequest(accountId.toStdString(), conversationId.toStdString()); + } + void declineConversationRequest(const QString& accountId, const QString& conversationId) + { + DRing::declineConversationRequest(accountId.toStdString(), conversationId.toStdString()); + } + bool removeConversation(const QString& accountId, const QString& conversationId) + { + return DRing::removeConversation(accountId.toStdString(), conversationId.toStdString()); + } + QStringList getConversations(const QString& accountId) + { + auto conversations = DRing::getConversations(accountId.toStdString()); + return convertStringList(conversations); + } + VectorMapStringString getConversationRequests(const QString& accountId) + { + auto requests = DRing::getConversationRequests(accountId.toStdString()); + return convertVecMap(requests); + } + void addConversationMember(const QString& accountId, + const QString& conversationId, + const QString& memberId) + { + DRing::addConversationMember(accountId.toStdString(), + conversationId.toStdString(), + memberId.toStdString()); + } + void removeConversationMember(const QString& accountId, + const QString& conversationId, + const QString& memberId) + { + DRing::removeConversationMember(accountId.toStdString(), + conversationId.toStdString(), + memberId.toStdString()); + } + VectorMapStringString getConversationMembers(const QString& accountId, + const QString& conversationId) + { + auto members = DRing::getConversationMembers(accountId.toStdString(), + conversationId.toStdString()); + return convertVecMap(members); + } + void sendMessage(const QString& accountId, + const QString& conversationId, + const QString& message, + const QString& parent) + { + DRing::sendMessage(accountId.toStdString(), + conversationId.toStdString(), + message.toStdString(), + parent.toStdString()); + } + uint32_t loadConversationMessages(const QString& accountId, + const QString& conversationId, + const QString& fromId, + const int size) + { + return DRing::loadConversationMessages(accountId.toStdString(), + conversationId.toStdString(), + fromId.toStdString(), + size); + } + + void setDefaultModerator(const QString& accountID, const QString& peerURI, const bool& state) + { + DRing::setDefaultModerator(accountID.toStdString(), peerURI.toStdString(), state); + } + + QStringList getDefaultModerators(const QString& accountID) + { + return convertStringList(DRing::getDefaultModerators(accountID.toStdString())); + } + + void enableLocalModerators(const QString& accountID, const bool& isModEnabled) + { + DRing::enableLocalModerators(accountID.toStdString(), isModEnabled); + } + + bool isLocalModeratorsEnabled(const QString& accountID) + { + return DRing::isLocalModeratorsEnabled(accountID.toStdString()); + } + + void setAllModerators(const QString& accountID, const bool& allModerators) + { + DRing::setAllModerators(accountID.toStdString(), allModerators); + } + + bool isAllModerators(const QString& accountID) + { + return DRing::isAllModerators(accountID.toStdString()); + } + + MapStringString conversationInfos(const QString& accountId, const QString& conversationId) + { + return convertMap( + DRing::conversationInfos(accountId.toStdString(), conversationId.toStdString())); + } + + void updateConversationInfos(const QString& accountId, + const QString& conversationId, + const MapStringString& info) + { + DRing::updateConversationInfos(accountId.toStdString(), + conversationId.toStdString(), + convertMap(info)); + } + + uint32_t countInteractions(const QString& accountId, + const QString& conversationId, + const QString& toId, + const QString& fromId, + const QString& authorUri) + { + return DRing::countInteractions(accountId.toStdString(), + conversationId.toStdString(), + toId.toStdString(), + fromId.toStdString(), + authorUri.toStdString()); + } +Q_SIGNALS: // SIGNALS + void volumeChanged(const QString& device, double value); + void accountsChanged(); + void accountDetailsChanged(const QString& accountId, const MapStringString& details); + void historyChanged(); + void stunStatusFailure(const QString& reason); + void registrationStateChanged(const QString& accountID, + const QString& registration_state, + unsigned detail_code, + const QString& detail_str); + void stunStatusSuccess(const QString& message); + void errorAlert(int code); + void volatileAccountDetailsChanged(const QString& accountID, MapStringString details); + void certificatePinned(const QString& certId); + void certificatePathPinned(const QString& path, const QStringList& certIds); + void certificateExpired(const QString& certId); + void certificateStateChanged(const QString& accountId, + const QString& certId, + const QString& status); + void incomingTrustRequest(const QString& accountId, + const QString& conversdationId, + const QString& from, + const QByteArray& payload, + qulonglong timeStamp); + void knownDevicesChanged(const QString& accountId, const MapStringString& devices); + void exportOnRingEnded(const QString& accountId, int status, const QString& pin); + void incomingAccountMessage(const QString& accountId, + const QString& from, + const QString msgId, + const MapStringString& payloads); + void mediaParametersChanged(const QString& accountId); + void audioDeviceEvent(); + void audioMeter(const QString& id, float level); + void accountMessageStatusChanged(const QString& accountId, + const QString& conversationId, + const QString& peer, + const QString& messageId, + int status); + void nameRegistrationEnded(const QString& accountId, int status, const QString& name); + void registeredNameFound(const QString& accountId, + int status, + const QString& address, + const QString& name); + void migrationEnded(const QString& accountID, const QString& result); + void contactAdded(const QString& accountID, const QString& uri, bool banned); + void contactRemoved(const QString& accountID, const QString& uri, bool banned); + void profileReceived(const QString& accountID, const QString& peer, const QString& vCard); + void dataTransferEvent(const QString& accountId, + const QString& conversationId, + const QString& interactionId, + const QString& fileId, + uint code); + void deviceRevocationEnded(const QString& accountId, const QString& deviceId, int status); + void accountProfileReceived(const QString& accountId, + const QString& displayName, + const QString& userPhoto); + void messageSend(const QString& message); + void composingStatusChanged(const QString& accountId, + const QString& convId, + const QString& contactId, + bool isComposing); + void userSearchEnded(const QString& accountId, + int status, + const QString& query, + VectorMapStringString results); + // swarm + void conversationLoaded(uint32_t requestId, + const QString& accountId, + const QString& conversationId, + const VectorMapStringString& messages); + void messageReceived(const QString& accountId, + const QString& conversationId, + const MapStringString& message); + void conversationRequestReceived(const QString& accountId, + const QString& conversationId, + const MapStringString& metadatas); + void conversationRequestDeclined(const QString& accountId, const QString& conversationId); + void conversationReady(const QString& accountId, const QString& conversationId); + void conversationRemoved(const QString& accountId, const QString& conversationId); + void conversationMemberEvent(const QString& accountId, + const QString& conversationId, + const QString& memberId, + int event); +}; + +namespace org { +namespace ring { +namespace Ring { +typedef ::ConfigurationManagerInterface ConfigurationManager; +} +} // namespace ring +} // namespace org diff --git a/src/libclient/qtwrapper/conversions_wrap.hpp b/src/libclient/qtwrapper/conversions_wrap.hpp new file mode 100644 index 0000000000000000000000000000000000000000..74665949db866ecff87a65dab9c5a2a374eb1e92 --- /dev/null +++ b/src/libclient/qtwrapper/conversions_wrap.hpp @@ -0,0 +1,243 @@ +/****************************************************************************** + * Copyright (C) 2014-2022 by Savoir-faire Linux * + * Author : Philippe Groarke <philippe.groarke@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the Lesser GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +#ifndef CONVERSIONS_WRAP_H +#define CONVERSIONS_WRAP_H + +#include <map> +#include <string> +#include <vector> +#include <ctime> + +#include "../typedefs.h" + +#define Q_NOREPLY + +// Print all call to some signals +#ifdef VERBOSE_IPC +#define LOG_DRING_SIGNAL(name, arg) qDebug() << "\033[22;34m >>>>>> \033[0m" << name << arg; +#define LOG_DRING_SIGNAL2(name, arg, arg2) \ + qDebug() << "\033[22;34m >>>>>> \033[0m" << name << arg << arg2; +#define LOG_DRING_SIGNAL3(name, arg, arg2, arg3) \ + qDebug() << "\033[22;34m >>>>>> \033[0m" << name << arg << arg2 << arg3; +#define LOG_DRING_SIGNAL4(name, arg, arg2, arg3, arg4) \ + qDebug() << "\033[22;34m >>>>>> \033[0m" << name << arg << arg2 << arg3 << arg4; +#else +#define LOG_DRING_SIGNAL(name, args) // Nothing +#define LOG_DRING_SIGNAL2(name, arg, arg2) +#define LOG_DRING_SIGNAL3(name, arg, arg2, arg3) +#define LOG_DRING_SIGNAL4(name, arg, arg2, arg3, arg4) +#endif + +inline MapStringString +convertMap(const std::map<std::string, std::string>& m) +{ + MapStringString temp; + for (const auto& [key, value] : m) { + temp[QString(key.c_str())] = QString(value.c_str()); + } + return temp; +} + +inline std::map<std::string, std::string> +convertMap(const MapStringString& m) +{ + std::map<std::string, std::string> temp; + for (const auto& [key, value] : m.toStdMap()) { + temp[key.toStdString()] = value.toStdString(); + } + return temp; +} + +inline VectorMapStringString +convertVecMap(const std::vector<std::map<std::string, std::string>>& m) +{ + VectorMapStringString temp; + for (const auto& x : m) { + temp.push_back(convertMap(x)); + } + return temp; +} + +inline std::vector<std::map<std::string, std::string>> +convertVecMap(const VectorMapStringString& m) +{ + std::vector<std::map<std::string, std::string>> temp; + for (const auto& x : m) { + temp.push_back(convertMap(x)); + } + return temp; +} + +inline QStringList +convertStringList(const std::vector<std::string>& v) +{ + QStringList temp; + for (const auto& x : v) { + temp.push_back(QString(x.c_str())); + } + return temp; +} + +inline VectorString +convertVectorString(const std::vector<std::string>& v) +{ + VectorString temp; + for (const auto& x : v) { + temp.push_back(QString(x.c_str())); + } + return temp; +} + +inline std::vector<std::string> +convertVectorString(const VectorString& v) +{ + std::vector<std::string> temp; + for (const auto& x : v) { + temp.emplace_back(x.toStdString()); + } + return temp; +} + +inline std::map<std::string, std::vector<std::string>> +convertMap(const MapStringVectorString& m) +{ + std::map<std::string, std::vector<std::string>> temp; + for (const auto& [key, value] : m.toStdMap()) { + temp[key.toStdString()] = convertVectorString(value); + } + return temp; +} + +inline MapStringVectorString +convertMap(const std::map<std::string, std::vector<std::string>>& m) +{ + MapStringVectorString temp; + for (const auto& [key, value] : m) { + temp[QString(key.c_str())] = convertVectorString(value); + } + return temp; +} + +inline VectorULongLong +convertVectorULongLong(const std::vector<uint64_t>& v) +{ + VectorULongLong temp; + for (const auto& x : v) { + temp.push_back(x); + } + return temp; +} + +inline VectorUInt +convertVectorUnsignedInt(const std::vector<unsigned int>& v) +{ + VectorUInt temp; + for (const auto& x : v) { + temp.push_back(x); + } + return temp; +} + +inline std::vector<unsigned int> +convertStdVectorUnsignedInt(const VectorUInt& v) +{ + std::vector<unsigned int> temp; + for (const auto& x : v) { + temp.push_back(x); + } + return temp; +} + +inline std::vector<std::string> +convertStringList(const QStringList& v) +{ + std::vector<std::string> temp; + for (const auto& x : v) { + temp.push_back(x.toStdString()); + } + return temp; +} + +inline MapStringInt +convertStringInt(const std::map<std::string, int>& m) +{ + MapStringInt temp; + for (const auto& [key, value] : m) { + temp[QString(key.c_str())] = value; + } + return temp; +} + +constexpr static const char* TRUE_STR = "true"; +constexpr static const char* FALSE_STR = "false"; + +static inline QString +toQString(bool b) noexcept +{ + return b ? TRUE_STR : FALSE_STR; +} + +static inline QString +toQString(const std::string& str) noexcept +{ + return QString::fromStdString(str); +} + +static inline QString +toQString(int i) noexcept +{ + return QString::number(i); +} + +static inline QString +toQString(unsigned int i) noexcept +{ + return QString::number(i); +} + +static inline QString +toQString(uint64_t i) noexcept +{ + return QString::number(i); +} + +static inline bool +toBool(QString qs) noexcept +{ + return qs == TRUE_STR ? true : false; +} + +static inline int +toInt(QString qs) noexcept +{ + return qs.toInt(); +} + +static inline std::string +toStdString(QString qs) noexcept +{ + return qs.toStdString(); +} + +static inline QString +toQString(const std::time_t& t) noexcept +{ + return QString::fromStdString(std::to_string(t)); +} + +#endif // CONVERSIONS_WRAP_H diff --git a/src/libclient/qtwrapper/instancemanager.cpp b/src/libclient/qtwrapper/instancemanager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8279502b7b6e80f20a436c689d374a800adec621 --- /dev/null +++ b/src/libclient/qtwrapper/instancemanager.cpp @@ -0,0 +1,76 @@ +/**************************************************************************** + * Copyright (C) 2009-2022 Savoir-faire Linux Inc. * + * Authors : Alexandre Lision alexandre.lision@savoirfairelinux.com * + * Author : Alexandre Lision <alexandre.lision@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include "instancemanager_wrap.h" +#include "callmanager.h" +#include "presencemanager.h" +#include "configurationmanager.h" +#ifdef ENABLE_VIDEO +#include "videomanager.h" +#endif // ENABLE_VIDEO + +static int ringFlags = 0; + +InstanceManagerInterface::InstanceManagerInterface(bool muteDring) +{ + using namespace std::placeholders; + + using std::bind; + using DRing::exportable_callback; + using DRing::CallSignal; + using DRing::ConfigurationSignal; + using DRing::PresenceSignal; + using DRing::DataTransferSignal; + using DRing::ConversationSignal; + +#ifdef ENABLE_VIDEO + using DRing::VideoSignal; +#endif + +#ifndef MUTE_DRING + if (!muteDring) { + ringFlags |= DRing::DRING_FLAG_DEBUG; + ringFlags |= DRing::DRING_FLAG_CONSOLE_LOG; + } +#endif + + DRing::init(static_cast<DRing::InitFlag>(ringFlags)); + + registerSignalHandlers(CallManager::instance().callHandlers); + registerSignalHandlers(ConfigurationManager::instance().confHandlers); + registerSignalHandlers(PresenceManager::instance().presHandlers); + registerSignalHandlers(ConfigurationManager::instance().dataXferHandlers); +#ifdef ENABLE_VIDEO + registerSignalHandlers(VideoManager::instance().videoHandlers); +#endif + registerSignalHandlers(ConfigurationManager::instance().conversationsHandlers); + + if (!DRing::start()) + printf("Error initializing daemon\n"); + else + printf("Daemon is running\n"); +} + +InstanceManagerInterface::~InstanceManagerInterface() {} + +bool +InstanceManagerInterface::isConnected() +{ + return true; +} diff --git a/src/libclient/qtwrapper/instancemanager_wrap.h b/src/libclient/qtwrapper/instancemanager_wrap.h new file mode 100644 index 0000000000000000000000000000000000000000..bd60e7244b75d3e8cb7fefabb8f1e052bd931ca6 --- /dev/null +++ b/src/libclient/qtwrapper/instancemanager_wrap.h @@ -0,0 +1,72 @@ +/****************************************************************************** + * Copyright (C) 2014-2022 Savoir-faire Linux Inc. * + * Author : Philippe Groarke <philippe.groarke@savoirfairelinux.com> * + * Author : Alexandre Lision <alexandre.lision@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the Lesser GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +#pragma once + +#include <QObject> +#include <QByteArray> +#include <QList> +#include <QMap> +#include <QString> +#include <QStringList> +#include <QVariant> +#include <QTimer> + +#include "jami.h" +#include "../typedefs.h" +#include "conversions_wrap.hpp" + +/* + * Proxy class for interface org.ring.Ring.Instance + */ +class InstanceManagerInterface : public QObject +{ + Q_OBJECT +public: + InstanceManagerInterface(bool muteDring = false); + ~InstanceManagerInterface(); + + // TODO: These are not present in jami.h + +public Q_SLOTS: // METHODS + void Register(int pid, const QString& name) + { + Q_UNUSED(pid) // When directly linked, the PID is always the current process PID + Q_UNUSED(name) + } + + void Unregister(int pid) + { + Q_UNUSED(pid) // When directly linked, the PID is always the current process PID + DRing::fini(); + } + + bool isConnected(); + +private: +Q_SIGNALS: // SIGNALS + void started(); +}; + +namespace cx { +namespace Ring { +namespace Ring { +typedef ::InstanceManagerInterface Instance; +} +} // namespace Ring +} // namespace cx diff --git a/src/libclient/qtwrapper/pluginmanager.cpp b/src/libclient/qtwrapper/pluginmanager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8e7df407fb9261cb24cc643332adcf8f020d1f23 --- /dev/null +++ b/src/libclient/qtwrapper/pluginmanager.cpp @@ -0,0 +1,165 @@ +/****************************************************************************** + * Copyright (C) 2014-2022 Savoir-faire Linux Inc. * + * Author : Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the Lesser GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ + +#include "pluginmanager_wrap.h" + +bool +PluginManagerInterface::loadPlugin(const QString& path) +{ + return DRing::loadPlugin(path.toStdString()); +} + +bool +PluginManagerInterface::unloadPlugin(const QString& path) +{ + return DRing::unloadPlugin(path.toStdString()); +} + +MapStringString +PluginManagerInterface::getPluginDetails(const QString& path) +{ + return convertMap(DRing::getPluginDetails(path.toStdString())); +} + +QStringList +PluginManagerInterface::getInstalledPlugins() +{ + return convertStringList(DRing::getInstalledPlugins()); +} + +QStringList +PluginManagerInterface::getLoadedPlugins() +{ + return convertStringList(DRing::getLoadedPlugins()); +} + +int +PluginManagerInterface::installPlugin(const QString& jplPath, bool force) +{ + return DRing::installPlugin(jplPath.toStdString(), force); +} + +int +PluginManagerInterface::uninstallPlugin(const QString& pluginRootPath) +{ + return DRing::uninstallPlugin(pluginRootPath.toStdString()); +} + +QStringList +PluginManagerInterface::getCallMediaHandlers() +{ + return convertStringList(DRing::getCallMediaHandlers()); +} + +void +PluginManagerInterface::toggleCallMediaHandler(const QString& mediaHandlerId, + const QString& callId, + bool toggle) +{ + DRing::toggleCallMediaHandler(mediaHandlerId.toStdString(), callId.toStdString(), toggle); +} + +QStringList +PluginManagerInterface::getChatHandlers() +{ + return convertStringList(DRing::getChatHandlers()); +} + +void +PluginManagerInterface::toggleChatHandler(const QString& chatHandlerId, + const QString& accountId, + const QString& peerId, + bool toggle) +{ + DRing::toggleChatHandler(chatHandlerId.toStdString(), + accountId.toStdString(), + peerId.toStdString(), + toggle); +} + +QStringList +PluginManagerInterface::getCallMediaHandlerStatus(const QString& callId) +{ + return convertStringList(DRing::getCallMediaHandlerStatus(callId.toStdString())); +} + +MapStringString +PluginManagerInterface::getCallMediaHandlerDetails(const QString& mediaHandlerId) +{ + return convertMap(DRing::getCallMediaHandlerDetails(mediaHandlerId.toStdString())); +} + +QStringList +PluginManagerInterface::getChatHandlerStatus(const QString& accountId, const QString& peerId) +{ + return convertStringList( + DRing::getChatHandlerStatus(accountId.toStdString(), peerId.toStdString())); +} + +MapStringString +PluginManagerInterface::getChatHandlerDetails(const QString& chatHandlerId) +{ + return convertMap(DRing::getChatHandlerDetails(chatHandlerId.toStdString())); +} + +void +PluginManagerInterface::setPluginsEnabled(bool enable) +{ + DRing::setPluginsEnabled(enable); +} + +bool +PluginManagerInterface::getPluginsEnabled() +{ + return DRing::getPluginsEnabled(); +} + +VectorMapStringString +PluginManagerInterface::getPluginPreferences(const QString& path, const QString& accountId) +{ + VectorMapStringString temp; + for (auto x : DRing::getPluginPreferences(path.toStdString(), accountId.toStdString())) { + temp.push_back(convertMap(x)); + } + return temp; +} + +bool +PluginManagerInterface::setPluginPreference(const QString& path, + const QString& accountId, + const QString& key, + const QString& value) +{ + return DRing::setPluginPreference(path.toStdString(), + accountId.toStdString(), + key.toStdString(), + value.toStdString()); +} + +MapStringString +PluginManagerInterface::getPluginPreferencesValues(const QString& path, const QString& accountId) +{ + return convertMap( + DRing::getPluginPreferencesValues(path.toStdString(), accountId.toStdString())); +} + +bool +PluginManagerInterface::resetPluginPreferencesValues(const QString& path, const QString& accountId) +{ + return DRing::resetPluginPreferencesValues(path.toStdString(), accountId.toStdString()); +} diff --git a/src/libclient/qtwrapper/pluginmanagerMock.cpp b/src/libclient/qtwrapper/pluginmanagerMock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b54ff094c1d846bf3b8f0e8b60624a06257d5f73 --- /dev/null +++ b/src/libclient/qtwrapper/pluginmanagerMock.cpp @@ -0,0 +1,148 @@ +/****************************************************************************** + * Copyright (C) 2014-2022 Savoir-faire Linux Inc. * + * Author : Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the Lesser GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +#pragma once + +#include "pluginmanager_wrap.h" + +bool +PluginManagerInterface::loadPlugin(const QString& path) +{ + return false; +} + +bool +PluginManagerInterface::unloadPlugin(const QString& path) +{ + return false; +} + +MapStringString +PluginManagerInterface::getPluginDetails(const QString& path) +{ + return {}; +} + +QStringList +PluginManagerInterface::getInstalledPlugins() +{ + return {}; +} + +QStringList +PluginManagerInterface::getLoadedPlugins() +{ + return {}; +} + +int +PluginManagerInterface::installPlugin(const QString& jplPath, bool force) +{ + return 0; +} + +int +PluginManagerInterface::uninstallPlugin(const QString& pluginRootPath) +{ + return 0; +} + +QStringList +PluginManagerInterface::getCallMediaHandlers() +{ + return {}; +} + +void +PluginManagerInterface::toggleCallMediaHandler(const QString& mediaHandlerId, + const QString& callId, + bool toggle) +{} + +QStringList +PluginManagerInterface::getChatHandlers() +{ + return {}; +} + +void +PluginManagerInterface::toggleChatHandler(const QString& chatHandlerId, + const QString& accountId, + const QString& peerId, + bool toggle) +{} + +QStringList +PluginManagerInterface::getCallMediaHandlerStatus(const QString& callId) +{ + return {}; +} + +MapStringString +PluginManagerInterface::getCallMediaHandlerDetails(const QString& mediaHandlerId) +{ + return {}; +} + +QStringList +PluginManagerInterface::getChatHandlerStatus(const QString& accountId, const QString& peerId) +{ + return {}; +} + +MapStringString +PluginManagerInterface::getChatHandlerDetails(const QString& chatHandlerId) +{ + return {}; +} + +void +PluginManagerInterface::setPluginsEnabled(bool enable) +{} + +bool +PluginManagerInterface::getPluginsEnabled() +{ + return false; +} + +VectorMapStringString +PluginManagerInterface::getPluginPreferences(const QString& path, const QString& accountId) +{ + return {}; +} + +bool +PluginManagerInterface::setPluginPreference(const QString& path, + const QString& accountId, + const QString& key, + const QString& value) +{ + return false; +} + +MapStringString +PluginManagerInterface::getPluginPreferencesValues(const QString& path, const QString& accountId) +{ + return {}; +} + +bool +PluginManagerInterface::resetPluginPreferencesValues(const QString& path, const QString& accountId) +{ + return false; +} diff --git a/src/libclient/qtwrapper/pluginmanager_wrap.h b/src/libclient/qtwrapper/pluginmanager_wrap.h new file mode 100644 index 0000000000000000000000000000000000000000..eee887d04d18115b1ce980dc6b1bf1019d1fb120 --- /dev/null +++ b/src/libclient/qtwrapper/pluginmanager_wrap.h @@ -0,0 +1,102 @@ +/****************************************************************************** + * Copyright (C) 2014-2022 Savoir-faire Linux Inc. * + * Author : Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the Lesser GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +#pragma once + +#include <QtCore/QObject> +#include <QtCore/QByteArray> +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QVariant> +#include <QtCore/QTimer> + +#include "typedefs.h" +#ifdef ENABLE_PLUGIN +#include <plugin_manager_interface.h> +#endif +#include "conversions_wrap.hpp" + +/* + * Proxy class for interface org.ring.Ring.PluginManager + */ +class PluginManagerInterface : public QObject +{ + Q_OBJECT +public: + PluginManagerInterface() {} + ~PluginManagerInterface() {} + +public Q_SLOTS: // METHODS + + bool loadPlugin(const QString& path); + + bool unloadPlugin(const QString& path); + + MapStringString getPluginDetails(const QString& path); + + QStringList getInstalledPlugins(); + + QStringList getLoadedPlugins(); + + int installPlugin(const QString& jplPath, bool force); + + int uninstallPlugin(const QString& pluginRootPath); + + QStringList getCallMediaHandlers(); + + void toggleCallMediaHandler(const QString& mediaHandlerId, const QString& callId, bool toggle); + + QStringList getChatHandlers(); + + void toggleChatHandler(const QString& chatHandlerId, + const QString& accountId, + const QString& peerId, + bool toggle); + + QStringList getCallMediaHandlerStatus(const QString& callId); + + MapStringString getCallMediaHandlerDetails(const QString& mediaHandlerId); + + QStringList getChatHandlerStatus(const QString& accountId, const QString& peerId); + + MapStringString getChatHandlerDetails(const QString& chatHandlerId); + + void setPluginsEnabled(bool enable); + + bool getPluginsEnabled(); + + VectorMapStringString getPluginPreferences(const QString& path, const QString& accountId); + + bool setPluginPreference(const QString& path, + const QString& accountId, + const QString& key, + const QString& value); + + MapStringString getPluginPreferencesValues(const QString& path, const QString& accountId); + + bool resetPluginPreferencesValues(const QString& path, const QString& accountId); +}; + +namespace org { +namespace ring { +namespace Ring { +typedef ::PluginManagerInterface PluginManager; +} +} // namespace ring +} // namespace org diff --git a/src/libclient/qtwrapper/presencemanager_wrap.h b/src/libclient/qtwrapper/presencemanager_wrap.h new file mode 100644 index 0000000000000000000000000000000000000000..5d7fcb32d3f6d36c270183bd8e0a4056cb4e42aa --- /dev/null +++ b/src/libclient/qtwrapper/presencemanager_wrap.h @@ -0,0 +1,140 @@ +/****************************************************************************** + * Copyright (C) 2014-2022 Savoir-faire Linux Inc. * + * Author : Philippe Groarke <philippe.groarke@savoirfairelinux.com> * + * Author : Alexandre Lision <alexandre.lision@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the Lesser GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +#pragma once + +#include <QtCore/QObject> +#include <QtCore/QByteArray> +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QVariant> +#include <QtCore/QTimer> + +#include "typedefs.h" +#include <presencemanager_interface.h> +#include "conversions_wrap.hpp" + +/* + * Proxy class for interface org.ring.Ring.PresenceManager + */ +class PresenceManagerInterface : public QObject +{ + Q_OBJECT +public: + std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> presHandlers; + + PresenceManagerInterface() + { + using DRing::exportable_callback; + using DRing::PresenceSignal; + + presHandlers + = {exportable_callback<PresenceSignal::NewServerSubscriptionRequest>( + [this](const std::string& buddyUri) { + Q_EMIT this->newServerSubscriptionRequest(QString(buddyUri.c_str())); + }), + exportable_callback<PresenceSignal::ServerError>([this](const std::string& accountID, + const std::string& error, + const std::string& msg) { + Q_EMIT this->serverError(QString(accountID.c_str()), + QString(error.c_str()), + QString(msg.c_str())); + }), + exportable_callback<PresenceSignal::NewBuddyNotification>( + [this](const std::string& accountID, + const std::string& buddyUri, + bool status, + const std::string& lineStatus) { + Q_EMIT this->newBuddyNotification(QString(accountID.c_str()), + QString(buddyUri.c_str()), + status, + QString(lineStatus.c_str())); + }), + exportable_callback<PresenceSignal::SubscriptionStateChanged>( + [this](const std::string& accountID, const std::string& buddyUri, bool state) { + Q_EMIT this->subscriptionStateChanged(QString(accountID.c_str()), + QString(buddyUri.c_str()), + state); + }), + exportable_callback<PresenceSignal::NearbyPeerNotification>( + [this](const std::string& accountID, + const std::string& buddyUri, + int status, + const std::string& displayname) { + Q_EMIT this->nearbyPeerNotification(QString(accountID.c_str()), + QString(buddyUri.c_str()), + status, + QString(displayname.c_str())); + })}; + } + + ~PresenceManagerInterface() {} + +public Q_SLOTS: // METHODS + void answerServerRequest(const QString& uri, bool flag) + { + DRing::answerServerRequest(uri.toStdString(), flag); + } + + VectorMapStringString getSubscriptions(const QString& accountID) + { + VectorMapStringString temp; + for (auto x : DRing::getSubscriptions(accountID.toStdString())) { + temp.push_back(convertMap(x)); + } + return temp; + } + + void publish(const QString& accountID, bool status, const QString& note) + { + DRing::publish(accountID.toStdString(), status, note.toStdString()); + } + + void setSubscriptions(const QString& accountID, const QStringList& uriList) + { + DRing::setSubscriptions(accountID.toStdString(), convertStringList(uriList)); + } + + void subscribeBuddy(const QString& accountID, const QString& uri, bool flag) + { + DRing::subscribeBuddy(accountID.toStdString(), uri.toStdString(), flag); + } + +Q_SIGNALS: // SIGNALS + void nearbyPeerNotification(const QString& accountID, + const QString& buddyUri, + int status, + const QString& displayname); + void newServerSubscriptionRequest(const QString& buddyUri); + void serverError(const QString& accountID, const QString& error, const QString& msg); + void newBuddyNotification(const QString& accountID, + const QString& buddyUri, + bool status, + const QString& lineStatus); + void subscriptionStateChanged(const QString& accountID, const QString& buddyUri, bool state); +}; + +namespace org { +namespace ring { +namespace Ring { +typedef ::PresenceManagerInterface PresenceManager; +} +} // namespace ring +} // namespace org diff --git a/src/libclient/qtwrapper/videomanager_wrap.cpp b/src/libclient/qtwrapper/videomanager_wrap.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e1124ae84c323ff43df8d2260ebdbd823bd26646 --- /dev/null +++ b/src/libclient/qtwrapper/videomanager_wrap.cpp @@ -0,0 +1,47 @@ +/****************************************************************************** + * Copyright (C) 2014-2022 Savoir-faire Linux Inc. * + * Author : Philippe Groarke <philippe.groarke@savoirfairelinux.com> * + * Author : Alexandre Lision <alexandre.lision@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the Lesser GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +#include "videomanager_wrap.h" + +VideoManagerInterface::VideoManagerInterface() +{ +#ifdef ENABLE_VIDEO + using DRing::exportable_callback; + using DRing::VideoSignal; + videoHandlers + = {exportable_callback<VideoSignal::DeviceEvent>([this]() { Q_EMIT deviceEvent(); }), + exportable_callback<VideoSignal::DecodingStarted>([this](const std::string& id, + const std::string& shmPath, + int width, + int height, + bool isMixer) { + Q_EMIT decodingStarted(QString(id.c_str()), + QString(shmPath.c_str()), + width, + height, + isMixer); + }), + exportable_callback<VideoSignal::DecodingStopped>([this](const std::string& id, + const std::string& shmPath, + bool isMixer) { + Q_EMIT decodingStopped(QString(id.c_str()), QString(shmPath.c_str()), isMixer); + })}; +#endif +} + +VideoManagerInterface::~VideoManagerInterface() {} diff --git a/src/libclient/qtwrapper/videomanager_wrap.h b/src/libclient/qtwrapper/videomanager_wrap.h new file mode 100644 index 0000000000000000000000000000000000000000..64f1a24bedf8c832a633e7a8e7d6ce9d7d19a169 --- /dev/null +++ b/src/libclient/qtwrapper/videomanager_wrap.h @@ -0,0 +1,188 @@ +/****************************************************************************** + * Copyright (C) 2014-2022 Savoir-faire Linux Inc. * + * Author : Philippe Groarke <philippe.groarke@savoirfairelinux.com> * + * Author : Alexandre Lision <alexandre.lision@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the Lesser GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + *****************************************************************************/ +#pragma once + +// libstdc++ +#include <functional> + +// Qt +#include <QtCore/QObject> +#include <QtCore/QCoreApplication> +#include <QtCore/QByteArray> +#include <QtCore/QThread> +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QVariant> +#include <QtCore/QTimer> + +// Ring +#include <videomanager_interface.h> + +#include "typedefs.h" +#include "conversions_wrap.hpp" + +class VideoManagerInterface : public QObject +{ + Q_OBJECT + + friend class VideoManagerSignalProxy; + +public: + VideoManagerInterface(); + ~VideoManagerInterface(); + +#ifdef ENABLE_VIDEO + std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> videoHandlers; +#endif + +public Q_SLOTS: // METHODS + void applySettings(const QString& name, MapStringString settings) + { +#ifdef ENABLE_VIDEO + DRing::applySettings(name.toStdString(), convertMap(settings)); +#else + Q_UNUSED(name) + Q_UNUSED(settings) +#endif + } + + MapStringMapStringVectorString getCapabilities(const QString& name) + { + MapStringMapStringVectorString ret; +#ifdef ENABLE_VIDEO + std::map<std::string, std::map<std::string, std::vector<std::string>>> temp; + temp = DRing::getCapabilities(name.toStdString()); + + for (auto& x : temp) { + QMap<QString, VectorString> ytemp; + for (auto& y : x.second) { + ytemp[QString(y.first.c_str())] = convertVectorString(y.second); + } + ret[QString(x.first.c_str())] = ytemp; + } +#else + Q_UNUSED(name) +#endif + return ret; + } + + QString getDefaultDevice() + { +#ifdef ENABLE_VIDEO + return QString::fromStdString(DRing::getDefaultDevice().c_str()); +#else + return QString(); +#endif + } + + QStringList getDeviceList() + { +#ifdef ENABLE_VIDEO + QStringList temp = convertStringList(DRing::getDeviceList()); +#else + QStringList temp; +#endif + return temp; + } + + MapStringString getSettings(const QString& device) + { +#ifdef ENABLE_VIDEO + MapStringString temp = convertMap(DRing::getSettings(device.toStdString())); +#else + Q_UNUSED(device) + MapStringString temp; +#endif + return temp; + } + + void setDefaultDevice(const QString& name) + { +#ifdef ENABLE_VIDEO + DRing::setDefaultDevice(name.toStdString()); +#else + Q_UNUSED(name) +#endif + } + + QString openVideoInput(const QString& resource) + { +#ifdef ENABLE_VIDEO + return DRing::openVideoInput(resource.toStdString()).c_str(); +#endif + } + + void closeVideoInput(const QString& resource) + { +#ifdef ENABLE_VIDEO + DRing::closeVideoInput(resource.toStdString()); +#endif + } + + void startAudioDevice() { DRing::startAudioDevice(); } + + void stopAudioDevice() { DRing::stopAudioDevice(); } + + void registerSinkTarget(const QString& sinkID, const DRing::SinkTarget& target) + { +#ifdef ENABLE_VIDEO + DRing::registerSinkTarget(sinkID.toStdString(), target); +#else + Q_UNUSED(sinkID) + Q_UNUSED(target) +#endif + } + + bool getDecodingAccelerated() { return DRing::getDecodingAccelerated(); } + + void setDecodingAccelerated(bool state) { DRing::setDecodingAccelerated(state); } + + bool getEncodingAccelerated() { return DRing::getEncodingAccelerated(); } + + void setEncodingAccelerated(bool state) { DRing::setEncodingAccelerated(state); } + + void stopLocalRecorder(const QString& path) { DRing::stopLocalRecorder(path.toStdString()); } + + QString startLocalMediaRecorder(const QString& videoInputId, const QString& path) + { + return QString::fromStdString( + DRing::startLocalMediaRecorder(videoInputId.toStdString(), path.toStdString())); + } + + MapStringString getRenderer(const QString& id) + { + return convertMap(DRing::getRenderer(id.toStdString())); + } + +Q_SIGNALS: // SIGNALS + void deviceEvent(); + void decodingStarted( + const QString& id, const QString& shmPath, int width, int height, bool isMixer); + void decodingStopped(const QString& id, const QString& shmPath, bool isMixer); +}; + +namespace org { +namespace ring { +namespace Ring { +typedef ::VideoManagerInterface VideoManager; +} +} // namespace ring +} // namespace org diff --git a/src/libclient/renderer.cpp b/src/libclient/renderer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3a2065fd133cf170b092b78ad6e82b0f59f191fe --- /dev/null +++ b/src/libclient/renderer.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2018-2022 Savoir-faire Linux Inc. + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "renderer.h" + +#include <QSize> +#include <QMutex> + +namespace lrc { +namespace video { + +using namespace lrc::api::video; + +Renderer::Renderer(const QString& id, const QSize& res) + : id_(id) + , size_(res) + , QObject(nullptr) +{} + +Renderer::~Renderer() {} + +QString +Renderer::id() const +{ + return id_; +} + +QSize +Renderer::size() const +{ + return size_; +} + +void +Renderer::update(const QSize& size, const QString&) +{ + size_ = size; +} + +} // namespace video +} // namespace lrc diff --git a/src/libclient/renderer.h b/src/libclient/renderer.h new file mode 100644 index 0000000000000000000000000000000000000000..9e91bc29fdf01cd7f266be8311fd3a830d1d3349 --- /dev/null +++ b/src/libclient/renderer.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2018-2022 Savoir-faire Linux Inc. + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "api/video.h" +#include "typedefs.h" + +#include <QObject> +#include <QSize> + +#include <map> +#include <memory> +#include <string> +#include <vector> + +namespace lrc { +namespace video { + +class Renderer : public QObject +{ + Q_OBJECT +public: + Renderer(const QString& id, const QSize& res); + virtual ~Renderer(); + + /** + * @return renderer's id + */ + QString id() const; + + /** + * @return current renderer dimensions + */ + QSize size() const; + + /** + * Update size and shmPath of a renderer + * @param size new renderer dimensions + * @param shmPath new shmPath + */ + virtual void update(const QSize& size, const QString& shmPath = {}); + + /** + * @return current rendered frame + */ + virtual lrc::api::video::Frame currentFrame() const = 0; + +public Q_SLOTS: + virtual void startRendering() = 0; + virtual void stopRendering() = 0; + +Q_SIGNALS: + void frameUpdated(); + void stopped(); + void started(); + void frameBufferRequested(AVFrame* avFrame); + +private: + QString id_; + QSize size_; +}; + +} // namespace video +} // namespace lrc diff --git a/src/libclient/shmrenderer.cpp b/src/libclient/shmrenderer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8bbd2947d0e471805876b354991f25119edbd96a --- /dev/null +++ b/src/libclient/shmrenderer.cpp @@ -0,0 +1,351 @@ +/* + * Copyright (C) 2012-2022 Savoir-faire Linux Inc. + * Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> + * Author : Guillaume Roguez <guillaume.roguez@savoirfairelinux.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "shmrenderer.h" + +#include "dbus/videomanager.h" +#include "videomanager_interface.h" + +#include <QDebug> +#include <QMutex> +#include <QThread> + +#include <sys/ipc.h> +#include <sys/sem.h> +#include <sys/shm.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/mman.h> +#include <semaphore.h> +#include <errno.h> + +#ifndef CLOCK_REALTIME +#define CLOCK_REALTIME 0 +#endif + +#include <QTimer> + +#include <chrono> + +namespace lrc { + +using namespace api::video; + +namespace video { + +// Uncomment following line to output in console the FPS value +//#define DEBUG_FPS + +/* Shared memory object + * Implementation note: double-buffering + * Shared memory is divided in two regions, each representing one frame. + * First byte of each frame is warranted to by aligned on 16 bytes. + * One region is marked readable: this region can be safely read. + * The other region is writeable: only the producer can use it. + */ + +struct SHMHeader +{ + sem_t mutex; /*!< Lock it before any operations on following fields. */ + sem_t frameGenMutex; /*!< unlocked by producer when frameGen modified */ + unsigned frameGen; /*!< monotonically incremented when a producer changes readOffset */ + unsigned frameSize; /*!< size in bytes of 1 frame */ + unsigned mapSize; /*!< size to map if you need to see all data */ + unsigned readOffset; /*!< offset of readable frame in data */ + unsigned writeOffset; /*!< offset of writable frame in data */ + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wpedantic" + uint8_t data[]; /*!< the whole shared memory */ +#pragma GCC diagnostic pop +}; + +struct ShmRenderer::Impl final : public QObject +{ + Q_OBJECT +public: + Impl(ShmRenderer* parent) + : QObject(nullptr) + , parent_(parent) + , fd(-1) + , shmArea((SHMHeader*) MAP_FAILED) + , shmAreaLen(0) + , frameGen(0) + , fpsC(0) + , fps(0) + , timer(new QTimer(this)) +#ifdef DEBUG_FPS + , frameCount(0) + , lastFrameDebug(std::chrono::system_clock::now()) +#endif + { + timer->setInterval(33); + connect(timer, &QTimer::timeout, [this]() { Q_EMIT parent_->frameUpdated(); }); + VideoManager::instance().startShmSink(parent_->id(), true); + + parent_->moveToThread(&thread); + connect(&thread, &QThread::finished, [this] { parent_->stopRendering(); }); + thread.start(); + }; + ~Impl() + { + thread.quit(); + thread.wait(); + } + + // Constants + constexpr static const int FPS_RATE_SEC = 1; + constexpr static const int FRAME_CHECK_RATE_HZ = 120; + + // Lock the memory while the copy is being made + bool shmLock() { return ::sem_wait(&shmArea->mutex) >= 0; }; + + // Remove the lock, allow a new frame to be drawn + void shmUnlock() { ::sem_post(&shmArea->mutex); }; + + // Wait for new frame data from shared memory and save pointer. + bool getNewFrame(bool wait) + { + if (!shmLock()) + return false; + + if (frameGen == shmArea->frameGen) { + shmUnlock(); + + if (not wait) + return false; + + // wait for a new frame, max 33ms + static const struct timespec timeout = {0, 33000000}; + if (::sem_timedwait(&shmArea->frameGenMutex, &timeout) < 0) + return false; + + if (!shmLock()) + return false; + } + + // valid frame to render (daemon may have stopped)? + if (!shmArea->frameSize) { + shmUnlock(); + return false; + } + + // map frame data + if (!remapShm()) { + qDebug() << "Could not resize shared memory"; + return false; + } + + if (not frame) + frame.reset(new lrc::api::video::Frame); + frame->ptr = shmArea->data + shmArea->readOffset; + frame->size = shmArea->frameSize; + frameGen = shmArea->frameGen; + + shmUnlock(); + + ++fpsC; + + // Compute the FPS shown to the client + auto currentTime = std::chrono::system_clock::now(); + const std::chrono::duration<double> seconds = currentTime - lastFrameDebug; + if (seconds.count() >= FPS_RATE_SEC) { + fps = (int) (fpsC / seconds.count()); + fpsC = 0; + lastFrameDebug = currentTime; +#ifdef DEBUG_FPS + qDebug() << this << ": FPS " << fps; +#endif + } + + return true; + }; + + // Remap the shared memory. + // Shared memory is in an unlocked state if returns false (resize failed). + bool remapShm() + { + // This loop handles case where daemon resize shared memory + // during time we unlock it for remapping. + while (shmAreaLen != shmArea->mapSize) { + auto mapSize = shmArea->mapSize; + shmUnlock(); + + if (::munmap(shmArea, shmAreaLen)) { + qDebug() << "Could not unmap shared area: " << strerror(errno); + return false; + } + + shmArea + = (SHMHeader*) ::mmap(nullptr, mapSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + if (shmArea == MAP_FAILED) { + qDebug() << "Could not remap shared area: " << strerror(errno); + return false; + } + + if (!shmLock()) + return false; + + shmAreaLen = mapSize; + } + + return true; + }; + +private: + ShmRenderer* parent_; + +public: + QString path; + int fd; + SHMHeader* shmArea; + unsigned shmAreaLen; + uint frameGen; + + int fpsC; + int fps; + std::chrono::time_point<std::chrono::system_clock> lastFrameDebug; + + QTimer* timer; + QMutex mutex; + QThread thread; + std::shared_ptr<lrc::api::video::Frame> frame; +}; + +ShmRenderer::ShmRenderer(const QString& id, const QSize& res, const QString& shmPath) + : Renderer(id, res) + , pimpl_(std::make_unique<ShmRenderer::Impl>(this)) +{ + pimpl_->path = shmPath; +} + +ShmRenderer::~ShmRenderer() +{ + VideoManager::instance().startShmSink(id(), false); + stopShm(); +} + +void +ShmRenderer::update(const QSize& res, const QString& shmPath) +{ + Q_EMIT stopped(); + Renderer::update(res); + + if (!pimpl_->thread.isRunning()) + pimpl_->thread.start(); + + pimpl_->path = shmPath; + VideoManager::instance().startShmSink(id(), true); + Q_EMIT started(); +} + +Frame +ShmRenderer::currentFrame() const +{ + QMutexLocker lk {&pimpl_->mutex}; + if (pimpl_->getNewFrame(false)) { + if (auto frame_ptr = pimpl_->frame) + return std::move(*frame_ptr); + } + return {}; +} + +bool +ShmRenderer::startShm() +{ + if (pimpl_->fd != -1) { + qWarning() << "fd must be -1"; + return false; + } + + pimpl_->fd = ::shm_open(pimpl_->path.toLatin1(), O_RDWR, 0); + + if (pimpl_->fd < 0) { + qWarning() << "could not open shm area" << pimpl_->path + << ", shm_open failed:" << strerror(errno); + return false; + } + + // Map only header data + const auto mapSize = sizeof(SHMHeader); + pimpl_->shmArea + = (SHMHeader*) ::mmap(nullptr, mapSize, PROT_READ | PROT_WRITE, MAP_SHARED, pimpl_->fd, 0); + + if (pimpl_->shmArea == MAP_FAILED) { + qWarning() << "Could not remap shared area"; + return false; + } + + pimpl_->shmAreaLen = mapSize; + return true; +} + +void +ShmRenderer::stopShm() +{ + if (pimpl_->fd < 0) + return; + + pimpl_->timer->stop(); + + // Emit the signal before closing the file, this lower the risk of invalid + // memory access + Q_EMIT stopped(); + + { + QMutexLocker lk(&pimpl_->mutex); + // reset the frame so it doesn't point to an old value + pimpl_->frame.reset(); + } + + ::close(pimpl_->fd); + pimpl_->fd = -1; + + if (pimpl_->shmArea == MAP_FAILED) + return; + + ::munmap(pimpl_->shmArea, pimpl_->shmAreaLen); + pimpl_->shmAreaLen = 0; + pimpl_->shmArea = (SHMHeader*) MAP_FAILED; +} + +void +ShmRenderer::startRendering() +{ + QMutexLocker lk(&pimpl_->mutex); + + if (!startShm()) + return; + + pimpl_->timer->start(); + + Q_EMIT started(); +} + +// Done on destroy instead +void +ShmRenderer::stopRendering() +{} + +} // namespace video +} // namespace lrc + +#include "moc_shmrenderer.cpp" +#include "shmrenderer.moc" diff --git a/src/libclient/shmrenderer.h b/src/libclient/shmrenderer.h new file mode 100644 index 0000000000000000000000000000000000000000..7880432a1c5829ee217ea877b1691e15f2bdf109 --- /dev/null +++ b/src/libclient/shmrenderer.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2012-2022 Savoir-faire Linux Inc. + * Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "renderer.h" +#include "typedefs.h" + +namespace lrc { +namespace video { + +class ShmRenderer final : public Renderer +{ + Q_OBJECT +public: + ShmRenderer(const QString& id, const QSize& res, const QString& shmPath); + ~ShmRenderer(); + + // Renderer interface. + void update(const QSize& res, const QString& shmPath) override; + lrc::api::video::Frame currentFrame() const override; + + void stopShm(); + bool startShm(); + +public Q_SLOTS: + void startRendering() override; + void stopRendering() override; + +private: + struct Impl; + std::unique_ptr<Impl> pimpl_; +}; + +} // namespace video +} // namespace lrc diff --git a/src/libclient/smartinfohub.cpp b/src/libclient/smartinfohub.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dd9d11ba9a6bc697a4f43023436725cac24396af --- /dev/null +++ b/src/libclient/smartinfohub.cpp @@ -0,0 +1,178 @@ +/**************************************************************************** + * Copyright (C) 2016-2022 Savoir-faire Linux Inc. * + * Author: Olivier Grégoire <olivier.gregoire@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include "smartinfohub.h" +#include "private/smartInfoHub_p.h" + +#include <dbus/videomanager.h> +#include <dbus/callmanager.h> +#include <dbus/callmanager.h> + +SmartInfoHub::SmartInfoHub() +{ + d_ptr = new SmartInfoHubPrivate; + connect(&CallManager::instance(), + &CallManagerInterface::SmartInfo, + this, + &SmartInfoHub::slotSmartInfo, + Qt::QueuedConnection); +} + +SmartInfoHub::~SmartInfoHub() {} + +void +SmartInfoHub::start() +{ + CallManager::instance().startSmartInfo(d_ptr->m_refreshTimeInformationMS); +} + +void +SmartInfoHub::stop() +{ + CallManager::instance().stopSmartInfo(); +} + +SmartInfoHub& +SmartInfoHub::instance() +{ + // Singleton + static SmartInfoHub instance_; + return instance_; +} + +void +SmartInfoHub::setRefreshTime(uint32_t timeMS) +{ + d_ptr->m_refreshTimeInformationMS = timeMS; +} + +// Retrieve information from the map and implement all the variables +void +SmartInfoHub::slotSmartInfo(const MapStringString& map) +{ + for (int i = 0; i < map.size(); i++) + d_ptr->m_information[map.keys().at(i)] = map[map.keys().at(i)]; + + Q_EMIT changed(); +} +// Getter + +bool +SmartInfoHub::isConference() const +{ + return (d_ptr->m_information["type"] == "conference"); +} + +float +SmartInfoHub::localFps() const +{ + if (!d_ptr->m_information[LOCAL_FPS].isEmpty()) + return d_ptr->m_information[LOCAL_FPS].toFloat(); + + return 0.0; +} + +float +SmartInfoHub::remoteFps() const +{ + if (!d_ptr->m_information[REMOTE_FPS].isEmpty()) + return d_ptr->m_information[REMOTE_FPS].toFloat(); + + return 0.0; +} + +int +SmartInfoHub::remoteWidth() const +{ + if (!d_ptr->m_information[REMOTE_WIDTH].isEmpty()) + return d_ptr->m_information[REMOTE_WIDTH].toInt(); + else + return 0; +} + +int +SmartInfoHub::remoteHeight() const +{ + if (!d_ptr->m_information[REMOTE_HEIGHT].isEmpty()) + return d_ptr->m_information[REMOTE_HEIGHT].toInt(); + else + return 0; +} + +int +SmartInfoHub::localWidth() const +{ + if (!d_ptr->m_information[LOCAL_WIDTH].isEmpty()) + return d_ptr->m_information[LOCAL_WIDTH].toInt(); + else + return 0; +} + +int +SmartInfoHub::localHeight() const +{ + if (!d_ptr->m_information[LOCAL_HEIGHT].isEmpty()) + return d_ptr->m_information[LOCAL_HEIGHT].toInt(); + else + return 0; +} + +QString +SmartInfoHub::callID() const +{ + if (!d_ptr->m_information[CALL_ID].isEmpty()) + return d_ptr->m_information[CALL_ID]; + else + return SmartInfoHubPrivate::DEFAULT_RETURN_VALUE_QSTRING; +} + +QString +SmartInfoHub::localVideoCodec() const +{ + if (!d_ptr->m_information[LOCAL_VIDEO_CODEC].isEmpty()) + return d_ptr->m_information[LOCAL_VIDEO_CODEC]; + else + return SmartInfoHubPrivate::DEFAULT_RETURN_VALUE_QSTRING; +} + +QString +SmartInfoHub::localAudioCodec() const +{ + if (!d_ptr->m_information[LOCAL_AUDIO_CODEC].isEmpty()) + return d_ptr->m_information[LOCAL_AUDIO_CODEC]; + else + return SmartInfoHubPrivate::DEFAULT_RETURN_VALUE_QSTRING; +} + +QString +SmartInfoHub::remoteVideoCodec() const +{ + if (!d_ptr->m_information[REMOTE_VIDEO_CODEC].isEmpty()) + return d_ptr->m_information[REMOTE_VIDEO_CODEC]; + else + return SmartInfoHubPrivate::DEFAULT_RETURN_VALUE_QSTRING; +} + +QString +SmartInfoHub::remoteAudioCodec() const +{ + if (!d_ptr->m_information[REMOTE_AUDIO_CODEC].isEmpty()) + return d_ptr->m_information[REMOTE_AUDIO_CODEC]; + else + return SmartInfoHubPrivate::DEFAULT_RETURN_VALUE_QSTRING; +} diff --git a/src/libclient/smartinfohub.h b/src/libclient/smartinfohub.h new file mode 100644 index 0000000000000000000000000000000000000000..42b84e0281220bc0c70f6c52f68d97bc1fc5f52d --- /dev/null +++ b/src/libclient/smartinfohub.h @@ -0,0 +1,65 @@ +/**************************************************************************** + * Copyright (C) 2016-2022 Savoir-faire Linux Inc. * + * Author: Olivier Grégoire <olivier.gregoire@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#pragma once + +#include <QObject> +#include "typedefs.h" + +class SmartInfoHubPrivate; + +class SmartInfoHub final : public QObject +{ + Q_OBJECT +public: + // Singleton + static SmartInfoHub& instance(); + + void start(); + void stop(); + + void setRefreshTime(uint32_t timeMS); + + // Getter + float localFps() const; + float remoteFps() const; + int remoteWidth() const; + int remoteHeight() const; + int localWidth() const; + int localHeight() const; + QString callID() const; + QString localVideoCodec() const; + QString localAudioCodec() const; + QString remoteVideoCodec() const; + QString remoteAudioCodec() const; + bool isConference() const; + +Q_SIGNALS: + /// Emitted when informations have changed + void changed(); + +private Q_SLOTS: + void slotSmartInfo(const MapStringString& info); + +private: + // use to initialise the connection between the Qsignal and the lambda function + SmartInfoHub(); + virtual ~SmartInfoHub(); + + SmartInfoHubPrivate* d_ptr; +}; diff --git a/src/libclient/typedefs.h b/src/libclient/typedefs.h new file mode 100644 index 0000000000000000000000000000000000000000..c22ceadc01d846206d12dae7cf13dd0a7463fd68 --- /dev/null +++ b/src/libclient/typedefs.h @@ -0,0 +1,219 @@ +/**************************************************************************** + * Copyright (C) 2009-2022 Savoir-faire Linux Inc. * + * Author : Jérémy Quentin <jeremy.quentin@savoirfairelinux.com> * + * Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +// Qt +#include <QtCore/QMetaType> +#include <QtCore/QMap> +#include <QtCore/QVector> +#include <QtCore/QString> +#include <QtCore/QDebug> +#include <QtCore/QDateTime> + +// Typedefs (required to avoid '<' and '>' in the DBus XML) +typedef QMap<QString, QString> MapStringString; +typedef QMap<QString, int> MapStringInt; +typedef QVector<int> VectorInt; +typedef QVector<uint> VectorUInt; +typedef QVector<qulonglong> VectorULongLong; +typedef QVector<QMap<QString, QString>> VectorMapStringString; +typedef QVector<QString> VectorString; +typedef QMap<QString, QMap<QString, QVector<QString>>> MapStringMapStringVectorString; +typedef QMap<QString, QVector<QString>> MapStringVectorString; +typedef QMap<QString, QMap<QString, QStringList>> MapStringMapStringStringList; +typedef QMap<QString, QStringList> MapStringStringList; +typedef QVector<QByteArray> VectorVectorByte; +typedef uint64_t DataTransferId; + +// Adapted from libring DRing::DataTransferInfo +struct DataTransferInfo +{ + QString accountId; + quint32 lastEvent; + quint32 flags; + qlonglong totalSize; + qlonglong bytesProgress; + QString author; + QString peer; + QString conversationId; + QString displayName; + QString path; + QString mimetype; +}; + +struct Message +{ + QString from; + MapStringString payloads; + quint64 received; +}; + +typedef QVector<Message> messages; + +/** + * This function add a safe way to get an enum class size + * @note it cannot be "const" due to some compiler issues + * @note it cannot be unsigned to avoid some compiler warnings + */ +template<typename A> +constexpr int +enum_class_size() +{ + return static_cast<int>(A::COUNT__); +} + +#ifdef LRC_IMPORT +#define LIB_EXPORT Q_DECL_IMPORT +#else +#if defined(_MSC_VER) +#define LIB_EXPORT +#else +#define LIB_EXPORT Q_DECL_EXPORT +#endif +#endif + +// Doesn't work +#if ((__GNUC_MINOR__ > 8) || (__GNUC_MINOR__ == 8)) +#define STRINGIFY(x) #x +#define IGNORE_NULL(content) \ + _Pragma(STRINGIFY(GCC diagnostic ignored "-Wzero-as-null-pointer-constant")) content +#else +#define IGNORE_NULL(content) content +#endif // ENABLE_IGNORE_NULL + +/** + * Create a safe pack of flags from an enum class. + * + * This class exist to ensure all sources come from the same enum and that it is + * never accidentally accidentally into an integer. + * + * This assume that the enum has been setup as flags. + */ +template<class T> +class LIB_EXPORT FlagPack +{ +public: + FlagPack() + : m_Flags(0) + {} + FlagPack(const T& base) + : m_Flags(static_cast<uint>(base)) + {} + FlagPack(const FlagPack<T>& other) + : m_Flags(other.m_Flags) + {} + + // Operator + FlagPack<T>& operator|(const T& other) + { + m_Flags |= static_cast<uint>(other); + return *this; + } + + FlagPack<T>& operator|(const FlagPack<T>& other) + { + m_Flags |= other.m_Flags; + return *this; + } + + FlagPack<T>& operator|=(const T& other) + { + m_Flags |= static_cast<uint>(other); + return *this; + } + + FlagPack<T>& operator|=(const FlagPack<T>& other) + { + m_Flags |= other.m_Flags; + return *this; + } + + FlagPack<T>& operator^=(const T& other) + { + m_Flags ^= static_cast<uint>(other); + return *this; + } + + FlagPack<T>& operator^=(const FlagPack<T>& other) + { + m_Flags ^= other.m_Flags; + return *this; + } + + FlagPack<T> operator&(const T& other) const + { + return FlagPack<T>(m_Flags & static_cast<uint>(other)); + } + + FlagPack<T> operator&(const FlagPack<T>& other) const + { + return FlagPack<T>(m_Flags & other.m_Flags); + } + + FlagPack<T>& operator=(const FlagPack<T>& other) + { + m_Flags = other.m_Flags; + return *this; + } + + bool operator!=(const T& other) const { return m_Flags != static_cast<uint>(other); } + + bool operator==(const T& other) const { return m_Flags == static_cast<uint>(other); } + + bool operator==(const FlagPack<T>& other) const { return m_Flags == other.m_Flags; } + + bool operator!() const { return !m_Flags; } + + operator bool() const { return m_Flags != 0; } + + uint value() const { return m_Flags; } + +private: + FlagPack(uint base) + : m_Flags(base) + {} + uint m_Flags; +}; + +#ifdef _MSC_VER +#define DO_PRAGMA(x) /*do nothing*/ +#define __attribute__(A) /*do nothing*/ +#include <ciso646> +#else +#define DO_PRAGMA(x) _Pragma(#x) +#endif // _MSC_VER + +// Globally disable the "-Wunused-function" warning for GCC +// refs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55578 +#if ((__GNUC_MINOR__ > 8) || (__GNUC_MINOR__ == 8)) +#pragma GCC diagnostic ignored "-Wunused-function" +#endif + +#define DECLARE_ENUM_FLAGS(T) \ + DO_PRAGMA(GCC diagnostic push) \ + DO_PRAGMA(GCC diagnostic ignored "-Wunused-function") \ + __attribute__((unused)) static FlagPack<T> operator|(const T& first, const T& second) \ + { \ + FlagPack<T> p(first); \ + return p | second; \ + } \ + DO_PRAGMA(GCC diagnostic pop) + +#include <functional> +typedef std::function<void()> MigrationCb; diff --git a/src/libclient/uri.cpp b/src/libclient/uri.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7d3e36c7dcf8eef7111d8449fa6b058a758f6768 --- /dev/null +++ b/src/libclient/uri.cpp @@ -0,0 +1,619 @@ +/**************************************************************************** + * Copyright (C) 2014-2022 Savoir-faire Linux Inc. * + * Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> * + * Author : Hugo Lefeuvre <hugo.lefeuvre@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#include "uri.h" +#include <regex> + +class URIPimpl +{ +public: + // Strings associated with SchemeType + static const std::map<URI::SchemeType, const char*> schemeNames; + + // String associated with the transport name + static const std::map<URI::Transport, const char*> transportNames; + + struct Constants + { + constexpr static const char TRANSPORT[] = "transport"; + constexpr static const char TAG[] = "tag"; + }; + + URIPimpl(const URI& uri); + URIPimpl& operator=(const URIPimpl&); + + // Attributes + const URI& linked; + + QString m_ExtHostname; + QString m_Scheme; + QString m_Userinfo; + QStringList m_lAttributes; + QString m_Stripped; + QString m_Hostname2; + QByteArray m_Tag; + int m_Port = -1; + + URI::SchemeType m_HeaderType = URI::SchemeType::NONE; + URI::Transport m_Transport = URI::Transport::NOT_SET; + URI::ProtocolHint m_ProtocolHint = URI::ProtocolHint::UNRECOGNIZED; + + bool m_hasChevrons {false}; + bool m_Parsed {false}; + bool m_HasAt {false}; + bool m_HintParsed {false}; + bool m_IsHNParsed {false}; + + // Helpers + URI::Transport nameToTransport(const QByteArray& name); + static QString strip(const QString& uri, URI::SchemeType& schemeType, QString& scheme); + static bool checkIp(const QString& str, bool& isHash, const URI::SchemeType& scheme); + void parseAttribute(const QByteArray& extHn, const int start, const int pos); + void parseHostname(); + void parse(); +}; + +constexpr const char URIPimpl::Constants::TRANSPORT[]; +constexpr const char URIPimpl::Constants::TAG[]; + +const std::map<URI::Transport, const char*> URIPimpl::transportNames + = {{URI::Transport::NOT_SET, "NOT_SET"}, + {URI::Transport::TLS, "TLS"}, + {URI::Transport::tls, "tls"}, + {URI::Transport::TCP, "TCP"}, + {URI::Transport::tcp, "tcp"}, + {URI::Transport::UDP, "UDP"}, + {URI::Transport::udp, "udp"}, + {URI::Transport::SCTP, "SCTP"}, + {URI::Transport::sctp, "sctp"}, + {URI::Transport::DTLS, "DTLS"}, + {URI::Transport::dtls, "dtls"}}; + +const std::map<URI::SchemeType, const char*> URIPimpl::schemeNames + = {{URI::SchemeType::NONE, ""}, + {URI::SchemeType::SIP, "sip:"}, + {URI::SchemeType::SIPS, "sips:"}, + {URI::SchemeType::RING, "ring:"}}; + +URIPimpl::URIPimpl(const URI& uri) + : linked(uri) +{} + +URIPimpl& +URIPimpl::operator=(const URIPimpl& other) +{ + m_Parsed = other.m_Parsed; + m_HintParsed = other.m_HintParsed; + m_ExtHostname = other.m_ExtHostname; + m_HasAt = other.m_HasAt; + m_Scheme = other.m_Scheme; + m_ProtocolHint = other.m_ProtocolHint; + m_HeaderType = other.m_HeaderType; + m_Userinfo = other.m_Userinfo; + m_Stripped = other.m_Stripped; + m_IsHNParsed = other.m_IsHNParsed; + m_Port = other.m_Port; + m_Transport = other.m_Transport; + m_Tag = other.m_Tag; + m_hasChevrons = other.m_hasChevrons; + m_Hostname2 = other.m_Hostname2; + m_lAttributes = other.m_lAttributes; + return *this; +} + +URI::URI() + : QString() + , pimpl_(std::make_unique<URIPimpl>(*this)) +{} + +URI::URI(const QString& uri) + : URI() +{ + QString simplified = uri.simplified().remove(' ').remove('<').remove('>'); + pimpl_->m_Stripped = URIPimpl::strip(simplified, pimpl_->m_HeaderType, pimpl_->m_Scheme); + (*static_cast<QString*>(this)) = pimpl_->m_Stripped; +} + +URI::URI(const URI& other) + : URI() +{ + *pimpl_ = *other.pimpl_; + (*static_cast<QString*>(this)) = pimpl_->m_Stripped; +} + +URI& +URI::operator=(const URI& other) +{ + if (this != &other) { + *pimpl_ = *other.pimpl_; + (*static_cast<QString*>(this)) = pimpl_->m_Stripped; + } + return *this; +} + +URI::~URI() {} + +/** + * Strip out scheme from the URI + */ +QString +URIPimpl::strip(const QString& uri, URI::SchemeType& schemeType, QString& scheme) +{ + if (uri.isEmpty()) + return {}; + std::regex uri_regex = std::regex("(^sip:)|(^sips:)|(^ring:)|(^jami:)"); + std::string uri_to_match = uri.toStdString(); + std::smatch match; + + if (std::regex_search(uri_to_match, match, uri_regex)) { + if (match.ready()) { + scheme = match.str(0).c_str(); + } + } + + schemeType = URI::SchemeType::UNRECOGNIZED; + auto it = std::find_if(schemeNames.begin(), schemeNames.end(), [&scheme](auto& it) { + if (std::string(it.second) == "ring:" && scheme == "jami:") + return true; + return it.second == scheme; + }); + + if (it != URIPimpl::schemeNames.end()) + schemeType = it->first; + if (schemeType == URI::SchemeType::NONE) { + // no match, check if it includes x..x:..: format + std::regex uri_regex_unrecognized = std::regex("[a-zA-Z][a-zA-Z0-9+.-]*:"); + std::string uri_to_match_unrecognized = uri_to_match; + std::smatch match_unrecognized; + + if (std::regex_search(uri_to_match_unrecognized, + match_unrecognized, + uri_regex_unrecognized)) { + if (match_unrecognized.ready()) { + std::string scheme_unrecognized = match_unrecognized.str(0).c_str(); + if (!scheme_unrecognized.empty()) { + // match x..x:..: format + schemeType = URI::SchemeType::UNRECOGNIZED; + } + } + } + } + + return uri.mid(scheme.size(), uri.size()); +} + +/** + * Return the domain of the URI + * + * For example, example.com in <sip:12345@example.com> + */ +QString +URI::hostname() const +{ + if (!pimpl_->m_Parsed) + pimpl_->parse(); + return pimpl_->m_ExtHostname; +} + +/** + * Check if the URI has an hostname + * + * This will return true if there is something between '@' and ';' (or an end of line) + */ +bool +URI::hasHostname() const +{ + return !hostname().isEmpty(); +} + +/** + * If hasHostname() is true, this does a second parsing of the hostname to + * extract the port. + */ +bool +URI::hasPort() const +{ + return port() != -1; +} + +/** + * Return the port, -1 is none is set + */ +int +URI::port() const +{ + if (!pimpl_->m_IsHNParsed) { + pimpl_->parseHostname(); + } + return pimpl_->m_Port; +} + +/** + * Return the URI SchemeType + */ +URI::SchemeType +URI::schemeType() const +{ + if (!pimpl_->m_Parsed) + const_cast<URI*>(this)->pimpl_->parse(); + return pimpl_->m_HeaderType; +} + +/** + * "Fast" Ipv4 and Ipv6 check, accept 999.999.999.999, :::::::::FF and other + * atrocities, but at least perform a O(N) ish check and validate the hash + * + * @param str an uservalue (faster the scheme and before the "at" sign) + * @param [out] isHash if the content is pure hexadecimal ASCII + */ +bool +URIPimpl::checkIp(const QString& str, bool& isHash, const URI::SchemeType& scheme) +{ + const QByteArray raw = str.toLatin1(); + int max = str.size(); + + if (max < 3 || max > 45 || (!isHash && scheme == URI::SchemeType::RING)) + return false; + + uchar dc(0), sc(0), i(0), d(0), hx(1); + + while (i < max) { + switch (raw[i]) { + case '.': + isHash = false; + d = 0; + dc++; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (++d > 3 && dc) + return false; + break; + case ':': + isHash = false; + sc++; + // No break + [[clang::fallthrough]]; + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + hx = 0; + break; + default: + isHash = false; + return false; + } + i++; + } + return (hx && dc == 3 && d < 4) ^ (sc > 1 && dc == 0); +} + +/** + * This method return an hint to guess the protocol that could be used to call + * this URI. It is a quick guess, not something that should be trusted + * + * @warning, this method is O(N) when called for the first time on an URI + */ +URI::ProtocolHint +URI::protocolHint() const +{ + if (!pimpl_->m_Parsed) + pimpl_->parse(); + + if (!pimpl_->m_HintParsed) { + bool isHash = pimpl_->m_Userinfo.size() == 40; + + URI::ProtocolHint hint; + + // Step 1: Check IP + if (URIPimpl::checkIp(pimpl_->m_Userinfo, isHash, pimpl_->m_HeaderType)) { + hint = URI::ProtocolHint::IP; + } + // Step 2: Check RING hash + else if (isHash) { + hint = URI::ProtocolHint::RING; + } + // Step 3: Not a hash but it begins with ring:. This is a username. + else if (pimpl_->m_HeaderType == URI::SchemeType::RING) { + hint = URI::ProtocolHint::RING_USERNAME; + } + // Step 4: Check for SIP URIs + else if (pimpl_->m_HeaderType == URI::SchemeType::SIP) { + // Step 4.1: Check for SIP URI with hostname + if (pimpl_->m_HasAt) { + hint = URI::ProtocolHint::SIP_HOST; + } + // Step 4.2: Assume SIP URI without hostname + else { + hint = URI::ProtocolHint::SIP_OTHER; + } + } + // Step 5: UNRECOGNIZED + else { + hint = URI::ProtocolHint::UNRECOGNIZED; + } + + pimpl_->m_ProtocolHint = hint; + pimpl_->m_HintParsed = true; + } + return pimpl_->m_ProtocolHint; +} + +// Convert the transport name to a string +URI::Transport +URIPimpl::nameToTransport(const QByteArray& name) +{ + auto it = std::find_if(transportNames.begin(), transportNames.end(), [&name](auto& entry) { + return entry.second == name; + }); + + if (it != transportNames.end()) { + return it->first; + } else { + return URI::Transport::NOT_SET; + } +} + +// Keep a cache of the values to avoid re-parsing them +void +URIPimpl::parse() +{ + // FIXME the indexOf is done twice, the second time could be avoided + if (linked.indexOf('@') != -1) { + const QStringList split = linked.split('@'); + m_HasAt = true; + m_ExtHostname = split[1]; + m_Userinfo = split[0]; + m_Parsed = true; + } else { + m_Userinfo = (linked); + } +} + +void +URIPimpl::parseAttribute(const QByteArray& extHn, const int start, const int pos) +{ + const QList<QByteArray> parts = extHn.mid(start + 1, pos - start).split('='); + + if (parts.size() == 2) { + if (parts[0].toLower() == Constants::TRANSPORT) { + m_Transport = nameToTransport(parts[1]); + } else if (parts[0].toLower() == Constants::TAG) { + m_Tag = parts[1]; + } + } +} + +// Extract the hostname, port and attributes +void +URIPimpl::parseHostname() +{ + if (!m_Parsed) + parse(); + + const QByteArray extHn = linked.hostname().toLatin1(); + int length(extHn.size()), start(0); + bool inAttributes = false; + + URI::Section section = URI::Section::HOSTNAME; + + // in case no port, attributes, etc are provided + m_Hostname2 = linked.hostname(); + + for (int i = 0; i < length; i++) { + const char c = extHn[i]; + switch (c) { + case ':': // Begin port + if (section == URI::Section::HOSTNAME) { + m_Hostname2 = extHn.mid(start, i); + start = i; + section = URI::Section::PORT; + } + break; + case ';': // Begin attributes + if (inAttributes) { + parseAttribute(extHn, start, i); + } else { + if (section == URI::Section::HOSTNAME) { + m_Hostname2 = extHn.mid(start + 1, i - start); + } else if (section == URI::Section::PORT) { + m_Port = extHn.mid(start + 1, i - start - 1).toInt(); + } + inAttributes = true; + } + + start = i; + break; + case '#': // Begin fragments + // TODO handle fragments to comply to the RFC + break; + default: + break; + } + } + + // Get the remaining attribute + parseAttribute(extHn, start, length - 1); + m_IsHNParsed = true; +} + +/** + * Extract the user info field from the URI + * + * For example, "123" in sip:123@myserver.net + */ +QString +URI::userinfo() const +{ + if (!pimpl_->m_Parsed) + pimpl_->parse(); + return pimpl_->m_Userinfo; +} + +void +URI::setUserinfo(const QString& userinfo) +{ + pimpl_->m_Userinfo = userinfo; +} + +void +URI::setHostname(const QString& hostname) +{ + pimpl_->m_ExtHostname = hostname; +} + +void +URI::setPort(const QString& port) +{ + try { + pimpl_->m_Port = port.toInt(); + } catch (...) { + qWarning() << "Can't convert port to integer"; + } +} + +/** + * Sometime, some metadata can be used to deduce the scheme even if it wasn't + * originally known. + */ +void +URI::setSchemeType(SchemeType t) +{ + pimpl_->m_HeaderType = t; + pimpl_->m_Scheme = URIPimpl::schemeNames.at(t); +} + +/** + * Generate a new URI formatted with the sections passed in `sections` + * + * It is kept as a QString to avoid the URI class to start reformatting + * it right away. + */ +QString +URI::format(FlagPack<URI::Section> sections) const +{ + if (!pimpl_->m_IsHNParsed) { + pimpl_->parseHostname(); + } + + auto header_type = pimpl_->m_HeaderType; + if (header_type == SchemeType::NONE) { + switch (protocolHint()) { + case ProtocolHint::RING: + case ProtocolHint::RING_USERNAME: + header_type = SchemeType::RING; + break; + case ProtocolHint::SIP_HOST: + case ProtocolHint::SIP_OTHER: + case ProtocolHint::IP: + header_type = SchemeType::SIP; + break; + case ProtocolHint::UNRECOGNIZED: + default: + header_type = SchemeType::RING; + break; + } + } + + QString ret; + + if (sections & URI::Section::CHEVRONS) + ret += '<'; + + if (sections & URI::Section::SCHEME) { + if (header_type == SchemeType::UNRECOGNIZED) { + ret += pimpl_->m_Scheme; + } else { + ret += URIPimpl::schemeNames.at(header_type); + } + } + + if (sections & URI::Section::USER_INFO) + ret += pimpl_->m_Userinfo; + + if (sections & URI::Section::HOSTNAME && !pimpl_->m_Hostname2.isEmpty()) + ret += '@' + pimpl_->m_Hostname2; + + if (sections & URI::Section::PORT && pimpl_->m_Port != -1) + ret += ':' + QString::number(pimpl_->m_Port); + + if (sections & URI::Section::CHEVRONS) + ret += '>'; + + if (sections & URI::Section::TRANSPORT && pimpl_->m_Transport != URI::Transport::NOT_SET) + ret += ";transport=" + QString(URIPimpl::transportNames.at(pimpl_->m_Transport)); + + if (sections & URI::Section::TAG && !pimpl_->m_Tag.isEmpty()) + ret += ";tag=" + pimpl_->m_Tag; + + return ret; +} + +/** + * Helper function which returns a QString containing a uri formatted to include at minimum the + * SCHEME and USER_INFO, and also the HOSTNAME and PORT, if available. + */ +QString +URI::full() const +{ + return format(URI::Section::SCHEME | URI::Section::USER_INFO | URI::Section::HOSTNAME + | URI::Section::PORT); +} + +QDataStream& +operator<<(QDataStream& stream, const URI::ProtocolHint& ph) +{ + switch (ph) { + case URI::ProtocolHint::SIP_OTHER: + stream << QStringLiteral("SIP_OTHER"); + break; + case URI::ProtocolHint::RING: + case URI::ProtocolHint::RING_USERNAME: + stream << QStringLiteral("RING"); + break; + case URI::ProtocolHint::IP: + stream << QStringLiteral("IP"); + break; + case URI::ProtocolHint::SIP_HOST: + stream << QStringLiteral("SIP_HOST"); + break; + case URI::ProtocolHint::UNRECOGNIZED: + stream << QStringLiteral("UNRECOGNIZED"); + break; + } + + return stream; +} diff --git a/src/libclient/uri.h b/src/libclient/uri.h new file mode 100644 index 0000000000000000000000000000000000000000..a9c37f1870994843de6246a03b404e4b776296cb --- /dev/null +++ b/src/libclient/uri.h @@ -0,0 +1,196 @@ +/**************************************************************************** + * Copyright (C) 2014-2022 Savoir-faire Linux Inc. * + * Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> * + * Author : Hugo Lefeuvre <hugo.lefeuvre@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#include "typedefs.h" + +#include <memory> +#include <QStringList> + +class URIPimpl; +class QDataStream; + +/** + * @class URI A specialized string with multiple attributes + * + * Most of LibRingClient handle uri as strings, but more + * advanced algorithms need to access the various sections. + * This class implement a centralized and progressive URI + * parser to avoid having custom implementation peppered + * everywhere. This class doesn't attempt to produce perfect + * output. It has multiple tradeoff to be faster when + * accuracy has little value in the context of LibRingClient. + * + * Here is some example of common numbers/URIs: + * * 123 + * * 123@192.168.123.123 + * * 123@asterisk-server + * * <sip:123@192.168.123.123> + * * <sips:123@192.168.123.123> + * * <sips:888@192.168.48.213;transport=TLS> + * * <sip:c8oqz84zk7z@privacy.org>;tag=hyh8 + * * 1 800 123-4567 + * * 18001234567 + * + * @ref http://tools.ietf.org/html/rfc5456#page-8 + * @ref http://tools.ietf.org/html/rfc3986 + * @ref http://tools.ietf.org/html/rfc3261 + * @ref http://tools.ietf.org/html/rfc5630 + * + * <code> + * From the RFC: + * foo://example.com:8042/over/there?name=ferret#nose + * \_/ \______________/\_________/ \_________/ \__/ + * | | | | | + * scheme authority path query fragment + * | _____________________|__ + * / \ / \ + * urn:example:animal:ferret:nose + * + * authority = [ userinfo "@" ] host [ ":" port ] + * </code> + * + * "For example, the semicolon (";") and equals ("=") reserved characters are + * often used to delimit parameters and parameter values applicable to + * that segment. The comma (",") reserved character is often used for + * similar purposes. For example, one URI producer might use a segment + * such as "name;v=1.1" to indicate a reference to version 1.1 of + * "name", whereas another might use a segment such as "name,1.1" to + * indicate the same. " + */ +class LIB_EXPORT URI : public QString +{ +public: + URI(); + URI(const URI& other); + URI(const QString& other); + virtual ~URI(); + + // @enum SchemeType The very first part of the URI followed by a ':' + enum class SchemeType { SIP, SIPS, RING, NONE, COUNT__, UNRECOGNIZED }; + Q_ENUMS(URI::SchemeType) + + /** + * @enum Transport each known valid transport types + * Defined at http://tools.ietf.org/html/rfc3261#page-222 + */ + enum class Transport { + NOT_SET, /*!< The transport have not been set directly in the URI */ + TLS, /*!< Encrypted calls (capital) */ + tls, /*!< Encrypted calls */ + TCP, /*!< TCP (the default) (capital) */ + tcp, /*!< TCP (the default) */ + UDP, /*!< Without a connection (capital) */ + udp, /*!< Without a connection */ + SCTP, /*!< */ + sctp, /*!< */ + DTLS, /*!< */ + dtls, /*!< */ + COUNT__ + }; + Q_ENUMS(URI::Transport) + + /** + * @enum Section flags associated with each logical sections of the URI + * + * Those sections can be packed into a block to be used to define the + * expected URI syntax + * + */ + enum class Section { + CHEVRONS = 0x1 << 0, /*!< <code><sips:888@192.168.48.213:5060;transport=TLS> + \_/ \_/ + |_________________Chevrons_______________________| + </code>*/ + SCHEME = 0x1 << 1, /*!< <code><sips:888@192.168.48.213:5060;transport=TLS> + \___/ + |______Scheme|</code> */ + USER_INFO = 0x1 << 2, /*!< <code><sips:888@192.168.48.213:5060;transport=TLS> + \___/ + |_________Userinfo</code> */ + HOSTNAME = 0x1 << 3, /*!< <code><sips:888@192.168.48.213:5060;transport=TLS> + \______________/ + |_________Hostname</code> */ + PORT = 0x1 << 4, /*!< <code><sips:888@192.168.48.213:5060;transport=TLS> + \____/ + |_____Port</code> */ + TRANSPORT = 0x1 << 5, /*!< <code><sips:888@192.168.48.213:5060;transport=TLS> + \_____________/ + Transport________|</code> */ + TAG = 0x1 << 6, /*!< <code><sips:888@192.168.48.213:5060;tag=b5c73d9ef> + \_____________/ + Tag_________|</code> */ + }; + + /** + * @enum ProtocolHint Expanded version of Account::Protocol + * + * This is used to make better choice when it come to choose an account or + * guess if the URI can be used with the current set et configured accounts. + * + * @warning This is an approximation. Those values are guessed using partial + * parsing (for performance) and are not definitive. + */ + enum class ProtocolHint { + RING, /* Start with "ring:" and 45 ASCII chars OR 40 ASCII chars */ + IP, /* Match an IPv4 address */ + SIP_HOST, /* Start with "sip:", has an @ and no "ring:" prefix */ + SIP_OTHER, /* Start with "sip:" and doesn't fit in other categories */ + RING_USERNAME, /* Anything that starts with "ring:" and isn't followed by 40 ASCII chars */ + UNRECOGNIZED /* Anything that doesn't fit in other categories */ + }; + Q_ENUMS(URI::ProtocolHint) + + // Getter + QString hostname() const; + QString userinfo() const; + bool hasHostname() const; + bool hasPort() const; + int port() const; + SchemeType schemeType() const; + ProtocolHint protocolHint() const; + + // Setter + void setUserinfo(const QString& userinfo); + void setHostname(const QString& hostname); + void setPort(const QString& port); + void setSchemeType(SchemeType t); + + // Converter + QString format(FlagPack<URI::Section> sections) const; + + /** + * Helper function which returns a QString containing a uri formatted to include at minimum the + * SCHEME and USER_INFO, and also the HOSTNAME and PORT, if available. + */ + QString full() const; + + URI& operator=(const URI&); + +private: + std::unique_ptr<URIPimpl> pimpl_; +}; + +Q_DECLARE_METATYPE(URI) + +Q_DECLARE_METATYPE(URI::ProtocolHint) + +DECLARE_ENUM_FLAGS(URI::Section) + +QDataStream& operator<<(QDataStream& stream, const URI::ProtocolHint& ph); diff --git a/src/libclient/vcard.h b/src/libclient/vcard.h new file mode 100644 index 0000000000000000000000000000000000000000..8d1a603e20e2074dfc11b005fd1469a5a50ac630 --- /dev/null +++ b/src/libclient/vcard.h @@ -0,0 +1,109 @@ +/**************************************************************************** + * Copyright (C) 2017-2022 Savoir-faire Linux Inc. * + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * + * Author : Alexandre Lision <alexandre.lision@savoirfairelinux.com> * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ +#pragma once + +#include <QHash> +#include <QByteArray> + +namespace lrc { +namespace vCard { + +constexpr static const char* PROFILE_VCF = "x-ring/ring.profile.vcard"; + +struct Delimiter +{ + constexpr static const char* SEPARATOR_TOKEN = ";"; + constexpr static const char* END_LINE_TOKEN = "\n"; + constexpr static const char* BEGIN_TOKEN = "BEGIN:VCARD"; + constexpr static const char* END_TOKEN = "END:VCARD"; +}; + +struct Property +{ + constexpr static const char* UID = "UID"; + constexpr static const char* VERSION = "VERSION"; + constexpr static const char* ADDRESS = "ADR"; + constexpr static const char* AGENT = "AGENT"; + constexpr static const char* BIRTHDAY = "BDAY"; + constexpr static const char* CATEGORIES = "CATEGORIES"; + constexpr static const char* CLASS = "CLASS"; + constexpr static const char* DELIVERY_LABEL = "LABEL"; + constexpr static const char* EMAIL = "EMAIL"; + constexpr static const char* FORMATTED_NAME = "FN"; + constexpr static const char* GEOGRAPHIC_POSITION = "GEO"; + constexpr static const char* KEY = "KEY"; + constexpr static const char* LOGO = "LOGO"; + constexpr static const char* MAILER = "MAILER"; + constexpr static const char* NAME = "N"; + constexpr static const char* NICKNAME = "NICKNAME"; + constexpr static const char* NOTE = "NOTE"; + constexpr static const char* ORGANIZATION = "ORG"; + constexpr static const char* PHOTO = "PHOTO"; + constexpr static const char* PRODUCT_IDENTIFIER = "PRODID"; + constexpr static const char* REVISION = "REV"; + constexpr static const char* ROLE = "ROLE"; + constexpr static const char* SORT_STRING = "SORT-STRING"; + constexpr static const char* SOUND = "SOUND"; + constexpr static const char* TELEPHONE = "TEL"; + constexpr static const char* TIME_ZONE = "TZ"; + constexpr static const char* TITLE = "TITLE"; + constexpr static const char* URL = "URL"; + constexpr static const char* BASE64 = "ENCODING=BASE64"; + constexpr static const char* TYPE_PNG = "TYPE=PNG"; + constexpr static const char* TYPE_JPEG = "TYPE=JPEG"; + constexpr static const char* PHOTO_PNG = "PHOTO;ENCODING=BASE64;TYPE=PNG"; + constexpr static const char* PHOTO_JPEG = "PHOTO;ENCODING=BASE64;TYPE=JPEG"; + + constexpr static const char* X_RINGACCOUNT = "X-RINGACCOUNTID"; +}; + +namespace utils { +/** + * Payload to vCard + * @param content payload + * @return the vCard representation + */ +static QHash<QByteArray, QByteArray> +toHashMap(const QByteArray& content) +{ + // TODO without Qt + QHash<QByteArray, QByteArray> vCard; + QByteArray previousKey, previousValue; + const QList<QByteArray> lines = content.split('\n'); + + Q_FOREACH (const QByteArray& property, lines) { + // Ignore empty lines + if (property.size()) { + // Some properties are over multiple lines + if (property[0] == ' ' && previousKey.size()) { + previousValue += property.right(property.size() - 1); + } + + // Do not use split, URIs can have : in them + const int dblptPos = property.indexOf(':'); + const QByteArray k(property.left(dblptPos)), + v(property.right(property.size() - dblptPos - 1)); + vCard[k] = v; + } + } + return vCard; +} +} // namespace utils +} // namespace vCard +} // namespace lrc diff --git a/src/libclient/web-chatview/.eslintrc.json b/src/libclient/web-chatview/.eslintrc.json new file mode 100644 index 0000000000000000000000000000000000000000..746c54a40a2dda347f83854dd478ca9d217ac13b --- /dev/null +++ b/src/libclient/web-chatview/.eslintrc.json @@ -0,0 +1,31 @@ +{ + "env": { + "browser": true + }, + "plugins": ["html"], + "extends": "eslint:recommended", + "parserOptions": { + "ecmaVersion": 6 + }, + "rules": { + "indent": [ + "error", + 4 + ], + "linebreak-style": [ + "error", + "unix" + ], + "quotes": [ + "error", + "double" + ], + "semi": [ + "error", + "never" + ], + "no-inner-declarations": [ + 0 + ] + } +} diff --git a/src/libclient/web-chatview/README b/src/libclient/web-chatview/README new file mode 100644 index 0000000000000000000000000000000000000000..75b6bf9fe20b27b42a99b5e2416e0e0381d68219 --- /dev/null +++ b/src/libclient/web-chatview/README @@ -0,0 +1,33 @@ +# README - chatview + +The chatview runs under a WebKit GTK view. It is written using web technologies +(HTML5/CSS3/JS) and is responsible for displaying everything that deals with the +navbar, the messages, and the message bar. + +## Contributing - syntax + +We have a set of ESLint rules that define clear syntax rules (web/.eslintrc.json). + +You will need the following tools: + +- ESLint (The pluggable linting utility for JavaScript and JSX) + https://eslint.org/ +- ESLint HTML plugin (eslint-plugin-html) + https://www.npmjs.com/package/eslint-plugin-html + +Before pushing a patch, make sure that it passes ESLint: +$ eslint chatview.html + +Most trivial issues can be fixed using +$ eslint chatview.js --fix + +We will not accept patches introducing non-ESLint-compliant code. + +## WebKit GTK + +Everything runs under WebKit GTK, that is if you need to write browser specific +code, you will only need to support WebKit (CSS -webkit- prefix). + +Do not use querySelector if getElementById or getElementByClassName can be used +instead. querySelector doesn't always make the code easier and has very bad +performances. diff --git a/src/libclient/web-chatview/chatview-gnome.css b/src/libclient/web-chatview/chatview-gnome.css new file mode 100644 index 0000000000000000000000000000000000000000..18a751a055a4f992a345d5fea13229d54e41a296 --- /dev/null +++ b/src/libclient/web-chatview/chatview-gnome.css @@ -0,0 +1,49 @@ +.internal_mes_wrapper { + margin: 3px 0 0 0; +} + +.message_wrapper { + padding: 1em; +} + +.sender_image { + margin: 10px; +} + +.message_out + .message_out .message_wrapper { + border-top-right-radius: 10px; +} + +.message_in + .message_in .message_wrapper { + border-top-left-radius: 10px; +} + +.message_in + .message_in .sender_image { + visibility: hidden; +} + +.message_out + .message_out .sender_image { + visibility: hidden; +} + +.message_text { + hyphens: auto; + word-break: break-word; + word-wrap: break-word; +} + +.menuoption { + user-select: none; + cursor: pointer; +} + +#sendMessage { + height: var(--navbar-height); +} + +#sendMessage .nav-button, #sendMessage .nav-button.deactivated { + height: 28px; + width: 28px; + margin: 1px; + padding: 2px; +} diff --git a/src/libclient/web-chatview/chatview-qt.css b/src/libclient/web-chatview/chatview-qt.css new file mode 100644 index 0000000000000000000000000000000000000000..a2860055b40715a3c0b2a6958291b141331b185e --- /dev/null +++ b/src/libclient/web-chatview/chatview-qt.css @@ -0,0 +1,259 @@ +:root { + /* color definitions */ + --jami-light-blue: rgba(59, 193, 211, 0.3); + --jami-dark-blue: #003b4e; + --jami-green: #1ed0a8; + --jami-green-hover: #1ed0a8; + /* main properties */ + --bg-color: #ffffff; + /* navbar properties */ + --navbar-height: 40px; + --navbar-padding-top: 8px; + --navbar-padding-bottom: var(--navbar-padding-top); + /* message bar properties */ + --textarea-max-height: 150px; + --placeholder-text-color: #d3d3d3; + /* button properties */ + --action-icon-color: var(--jami-dark-blue); + --deactivated-icon-color: #bebebe; + --action-icon-hover-color: #ededed; + --action-critical-icon-hover-color: rgba(211, 77, 59, 0.3); /* complementary color of jami light blue */ + --action-critical-icon-press-color: rgba(211, 77, 59, 0.5); + --action-critical-icon-color: #4E1300; + --action-icon-press-color: rgba(212, 212, 212, 1.0); + --invite-hover-color: white; + --bg-text-input: white; +} + +body { + font-family: sans-serif; +} + +#container { + max-width: 1000px; + margin: auto; +} + +.nav-right { + float: right; +} +/* classic screens */ +@media screen and (max-width: 1920px), screen and (max-height: 1080px) { + .message_in { + padding-left: 0px; + } + + .message_out { + padding-right: 0px; + } +} + +#invite_contact_name { + font-weight: 700; +} + +.internal_mes_wrapper { + margin: 0px 0 0 0; +} + +.message_wrapper { + padding: 1em; +} + +.sender_image { + margin: 10px; +} + +.message_out + .message_out .message_wrapper { + border-top-right-radius: 10px; +} + +.message_in + .message_in .message_wrapper { + border-top-left-radius: 10px; +} + +.message_in + .message_in .sender_image { + visibility: hidden; +} + +.message_out + .message_out .sender_image { + visibility: hidden; +} + +.message_text { + hyphens: auto; + word-break: break-word; + word-wrap: break-word; +} + +.sender_image { + margin: 0px 10px 0px 10px; +} + +.message_in .sender_image, +.message_out .sender_image { + visibility: hidden; +} + +.message_in.last_of_sequence .sender_image, +.message_in.single_message .sender_image { + visibility: visible; +} + +.message_in.last_of_sequence .sender_image { + margin-top: 2px; +} + +.message_in.middle_of_sequence .sender_image { + margin-top: 0px; +} + +.generated_message.message_in .message_wrapper, +.generated_message.message_out .message_wrapper { + background-color: transparent !important; + border-radius: 0px !important; +} + +.single_message.message_in .message_wrapper, +.single_message.message_out .message_wrapper { + border-radius: 20px 20px 20px 20px; +} + +.last_of_sequence.message_in .message_wrapper { + border-radius: 4px 20px 20px 20px; +} + +.first_of_sequence.message_in .message_wrapper { + border-radius: 20px 20px 20px 4px; +} + +.middle_of_sequence.message_in .message_wrapper { + border-radius: 4px 20px 20px 5px; +} + +.last_of_sequence.message_out .message_wrapper { + border-radius: 20px 4px 20px 20px; +} + +.first_of_sequence.message_out .message_wrapper { + border-radius: 20px 20px 4px 20px; +} + +.middle_of_sequence.message_out .message_wrapper { + border-radius: 20px 5px 4px 20px; +} + +.middle_of_sequence .internal_mes_wrapper, +.last_of_sequence .internal_mes_wrapper, +.last_message .internal_mes_wrapper { + margin: 0px 0 0 0 !important; +} + +.message_out .sender_image { + margin: 8px; +} + +.first_of_sequence.message_out .internal_mes_wrapper, +.single_message.message_out .internal_mes_wrapper { + margin: 0px 0 0 0 !important; +} + +.sender_image_cell { + vertical-align: bottom; + min-width: 16px; +} + +.message_in .sender_image_cell { + min-width: 56px; +} + +.dummy_cell { + padding: 0; +} + +.timestamp_cell { + padding: 0; + max-width: 0px; + overflow: visible; + white-space: nowrap; +} + +.timestamp_cell_out { + padding: 0; + text-align: right; + direction: rtl; + max-width: 0px; + overflow: visible; + white-space: nowrap; +} + +table { + border-collapse: collapse; + border-spacing: 0 0px; + margin: 0; + padding: 0; +} + +.message_text { + word-break: break-all; + word-wrap: hyphenate; +} + +pre { + white-space: pre-wrap; +} + +.message:hover:not(.message_type_contact) .menu_interaction { + display: block; + opacity: 1; +} + +.message_type_text .internal_mes_wrapper { + padding: 0; +} + +.first_of_sequence .internal_mes_wrapper { + padding: 0.1em 0 0 0; +} + +.menuoption { + user-select: none; + cursor: pointer; +} + +.nav-button { + width: 30px; + height: 30px; + margin: 6px; + padding: 2px; +} + +.nav-button.deactivated { + width: 30px; + height: 30px; + margin: 6px; + padding: 2px; +} + +#sendMessage { + padding: 7px; +} + +#nav-contactid-alias { + font-weight: 500; + font-size: 1em; + font-family: 'Segoe UI Emoji'; +} + +#nav-contactid-bestId { + font-weight: 100; + font-size: .7em; + font-family: Verdana; + color: #c0c0c0; +} + +#typing_indicator_container { + display: none; + padding-bottom: 1.5em !important; + margin-top: 4px; +} diff --git a/src/libclient/web-chatview/chatview.css b/src/libclient/web-chatview/chatview.css new file mode 100644 index 0000000000000000000000000000000000000000..7eb550c186d511270c1aeb853872f4d8e1e89940 --- /dev/null +++ b/src/libclient/web-chatview/chatview.css @@ -0,0 +1,1514 @@ +/** Variable and font definitions */ + +:root { + /* color definitions */ + --jami-light-blue: rgba(59, 193, 211, 0.3); + --jami-dark-blue: #003b4e; + --jami-green: #219d55; + --jami-green-hover: #1f8b4c; + --text-color: black; + --hyperlink-color: var(--text-color); + --timestamp-color: #333; + --message-out-bg: #cfd8dc; + --message-out-txt: black; + --message-in-bg: #fdfdfd; + --message-in-txt: black; + --file-in-timestamp-color: #555; + --file-out-timestamp-color: #555; + + /* main properties */ + --bg-color: #f2f2f2; /* same as macOS client */ + + /* navbar properties */ + --navbar-height: 40px; + --navbar-padding-top: 8px; + --navbar-padding-bottom: var(--navbar-padding-top); + + /* message bar properties */ + --textarea-max-height: 150px; + --placeholder-text-color: #d3d3d3; + + /* button properties */ + --action-icon-color: var(--jami-dark-blue); + --deactivated-icon-color: #BEBEBE; + --action-icon-hover-color: var(--jami-light-blue); + --action-critical-icon-hover-color: rgba(211, 77, 59, 0.3); /* complementary color of ring light blue */ + --action-critical-icon-press-color: rgba(211, 77, 59, 0.5); + --action-critical-icon-color: #4E1300; + --action-icon-press-color: rgba(59, 193, 211, 0.5); + --invite-hover-color: white; + + --bg-text-input: white; + --bg-invitation-rect: white; + + /* hairline properties */ + --hairline-color: #d9d9d9; + --hairline-thickness: 0.2px; +} + +@font-face { + font-family: emoji; + + /* Fonts for text outside emoji blocks */ + src: local('Muli'), + local('Open sans'), + local('Helvetica'), + local('Segoe UI'), + local('sans-serif'), + local('Liberation Sans'), + local('Liberation Mono'), + local('Ubuntu'); +} + +@font-face { + font-family: emoji; + + src: local('Noto Color Emoji'), + local('Android Emoji'), + local('Twitter Color Emoji'); + + /* Emoji unicode blocks */ + unicode-range: U+1F300-1F5FF, U+1F600-1F64F, U+1F680-1F6FF, U+2600-26FF; +} + +/** Body */ + +body { + color: var(--text-color); + --messagebar-size: 57px; + margin: 0; + overflow: hidden; + background-color: var(--bg-color); + padding-bottom: 0; + /* disable selection highlight because it looks very bad */ + -webkit-user-select: text; +} + +::-webkit-scrollbar { + display: none; +} + +/** Navbar */ + +.navbar-wrapper { + /* on top, over everything and full width */ + position: fixed; + left:0; right:0; + z-index: 500; + top: 0; +} + +#navbar { + background-color: var(--bg-color); + padding-right: 8px; + padding-left: 8px; + padding-top: var(--navbar-padding-top); + padding-bottom: var(--navbar-padding-bottom); + height: var(--navbar-height); + overflow: hidden; + align-items: center; + + /* takes whole width */ + left:0; right:0; + + display: flex; +} + +.hiddenState { + /* Used to hide navbar and message bar */ + display: none !important; +} + +.svgicon { + display: block; + margin: auto; + width: 95%; + height: 95%; +} + +.nav-button { + width: 30px; + height: 30px; + display: flex; + cursor: pointer; + align-self: center; + align-content: center; + border-radius: 50%; +} + +.nav-button.deactivated { + width: 40px; + height: 40px; + align-self: center; + align-content: center; + display: flex; + border-radius: 50%; + cursor: auto; +} + +.action-button svg { + fill: var(--action-icon-color); +} + +.action-button.deactivated svg { + fill: var(--deactivated-icon-color); +} + +.message_out .filesvg { + fill: var(--message-out-txt); +} + +.message_in .filesvg { + fill: var(--message-in-txt); +} + +.non-action-button svg { + stroke: var(--action-icon-color); +} + +.action-button.deactivated svg { + fill: var(--deactivated-icon-color); + stroke: var(--deactivated-icon-color); +} + +.non-action-button:hover, .action-button:hover { + background: var(--action-icon-hover-color); +} + +.non-action-button:active, .action-button:active { + background: var(--action-icon-press-color); +} + +.action-button.deactivated:hover, .action-button.deactivated:active { + background: none; +} + +.action-critical-button svg { + fill: var(--action-critical-icon-color); +} + +.action-critical-button:hover { + background: var(--action-critical-icon-hover-color); +} + +.action-critical-button:active { + background: var(--action-critical-icon-press-color); +} + +#navbar #unbanButton, #navbar #addToConversationsButton { + display: none; +} + +#navbar.onBannedState #addToConvButton, #navbar.onBannedState #navbar.onBannedState #addToConversationsButton { + display: none; +} + +#navbar.onBannedState #unbanButton { + display: flex; +} + +/** Invitation */ + +#invitation { + width: 100%; + height: 100%; +} + +.note_container { + width: 100%; + position: absolute; + opacity: 1; + transition: opacity 0.3s linear; + text-overflow: elipsis; +} + + +#invitation_text_container { + top: 10%; +} + +#invitation_note_container { + bottom: 15%; +} + +#invitation_text { + margin: 0px 20px 0px 20px; + text-align: center; + overflow: hidden; + text-overflow: ellipsis; +} + +#invitation_note { + margin: 20px 20px 20px 20px; + text-align: center; + opacity: 0.5; +} + +#invitation_rect { + width: 375px; + height: 25%; + min-height: 220px; + max-height: 280px; + + background-color: var(--bg-invitation-rect); + transition: background-color 0.3s; + border-radius: 20px; + box-shadow: 7px 7px 30px #12000930; + transition: box-shadow 0.3s; + + position: absolute; + left: 50%; + top: 55%; + transform: translate(-50%, -75%); + transition: transform 0.8s; + + display: flex; + justify-content: center; +} + +#invite_image { + width: 112px; + height: 112px; + position: absolute; + top: -56px; + margin: 0 auto; + opacity: 1; + transition: opacity 0.3s; +} + +#quote_img_wrapper { + position: absolute; + top: 40px; + opacity: 1; + transition: opacity 0.3s; +} + + +#invite_text { + margin-top: 96px; + margin-bottom: auto; + width: 66%; + margin-left: auto; + margin-right: auto; +} + +#join_text { + text-align: center; + font-size: 1.2em; + line-height: 1.5; +} + +#note_text { + margin-top: 20px; + margin-bottom: 20px; + text-align: center; + font-size: .9em; + line-height: 1.5; +} + +#actions { + position: absolute; + margin: 0 auto; + + bottom: 15%; + width: 240px; + height: 25px; + max-height: 25px; + min-height: 25px; + + display: flex; + justify-content: space-between; +} + +/** Messaging bar */ +#sendMessage { + background-color: var(--bg-color); + display: flex; + overflow: hidden; + padding: 4px; + align-items: center; + position: relative; + left: 0; + right: 0; + top: 0; + z-index: 1; + + /* hairline */ + border-top: var(--hairline-thickness) solid var(--hairline-color); + border-bottom: var(--hairline-thickness) solid var(--hairline-color); +} + +#message { + flex: 1; + background-color: transparent; + overflow-y: hidden; + vertical-align: middle; + color: var(--text-color); + width: 100%; + resize: none; + border: none; + + padding-left: 20px; + + /* enable selection (it is globally disabled in the body) */ + -webkit-user-select: auto; +} + +#message_bar_container { + height: "auto"; + width: 100%; + min-height: 50px; + max-height: var(--textarea-max-height); + background-color: var(--bg-text-input); + border-radius: 25px 25px 0px 25px; + display: flex; + flex-direction: row; + vertical-align: middle; +} + +#message:focus{ + outline: none; +} + +#container[disabled] { + background-color: #ccc; +} + +input[placeholder], [placeholder], *[placeholder] { + color: var(--placeholder-text-color); +} + +/** Main chat view */ + +#lazyloading-icon { + margin: auto; + margin-bottom: 10px; + margin-top: 5px; + vertical-align: center; + width: 30px; + display: flex; +} + +#container { + position: relative; + height: 100%; + width: 100%; + margin: 0; + padding: 0; + + display: flex; + flex-direction: column; + + /* When there are not enough messages to occupy full height of the + container, make sure they are displayed at the bottom, not at the + top. */ + justify-content: flex-end; +} + +a:link { + text-decoration: none; + color: var(--hyperlink-color); + transition: all 0.2s ease-in-out; +} + +a:hover { + border: 0; +} + +#data_transfer_send_container { + position: relative; + display: none; + justify-content: flex-start; + left: 0; + right: 0; + min-height: 8em; + max-height: 8em; + border: 2px solid lightgray; + padding: 20px; + border-bottom: none; + color: var(--message-out-txt); + background-color: var(--message-out-bg); + overflow-x: scroll; +} + +#data_transfer_send_container::-webkit-scrollbar { + display: flex; + height: 8px; +} + +#data_transfer_send_container::-webkit-scrollbar-track { + background-color: var(--message-out-bg); +} + +#data_transfer_send_container::-webkit-scrollbar-thumb { + background-color: var(--bg-color); + } + +#data_transfer_send_container::after { + /*Create the margins with pseudo-elements*/ + /*to solve overflow:scroll and The Right Padding Problem*/ + content: ' '; + min-width: 20px; +} + +.img_wrapper { + position: relative; + max-width: 65px; + min-width: 65px; + max-height: 80px; + border: 3px solid rgba(255,255,255,0); + padding: 30px; + border-radius: 20px; + background-color: var(--message-out-bg); + display: flex; + justify-content: center; + align-items: center; + margin: 5px; +} + +/* Make the image responsive */ +.img_wrapper img { + height: 118px; + min-width: 131px; + object-fit: cover; + border-radius: 20px; +} + +/* Style the button and place it at the top right corner of the image */ +.img_wrapper .btn { + position: absolute; + color: #fff; + border: 1px solid #AEAEAE; + border-radius: 40%; + background: rgba(96,95,97,0.5); + font-size: 10px; + font-weight: bold; + top: -5%; + right: -5%; +} + +.img_wrapper .btn:hover { + background-color: lightgray; +} + +.img_wrapper .btn:focus { + outline: none; + color: var(--text-color); +} + +.file_wrapper { + position: relative; + max-width: 65px; + min-width: 65px; + max-height: 80px; + border: 3px solid rgba(255,255,255,0); + padding: 30px; + border-radius: 20px; + background-color: var(--message-in-bg); + display: inline-block; + justify-content: flex-start; + align-items: center; + margin: 5px; + font-family: sans-serif; +} + +.file_wrapper p { + overflow: hidden; + white-space: nowrap; + max-width: 95px; + min-width: 95px; + text-overflow: ellipsis; +} + +/* Style the button and place it at the top right corner of the image */ +.file_wrapper .btn { + position: absolute; + color: #fff; + border: 1px solid #AEAEAE; + border-radius: 40%; + background: rgba(96,95,97,0.5); + font-size: 10px; + font-weight: bold; + top: -5%; + right: -5%; +} + +.file_wrapper .btn:hover { + background-color: lightgray; +} + +.file_wrapper .btn:focus { + outline: none; + color: black; +} + +.file_wrapper .svgicon { + position: absolute; + max-width: 2em; + max-height: 25px; + margin-right: 2em; + top: 8%; + left: 1px; + fill: var(--message-in-txt); +} + +.file_wrapper .svgicon path, +.file_wrapper .svgicon polygon, +.file_wrapper .svgicon rect { + fill: var(--message-in-txt); +} + +.file_wrapper .svgicon circle { + stroke: #4691f6; + stroke-width: 1; +} + +.file_wrapper .fileinfo { + position: absolute; + top: 30%; + left: 7%; + color: var(--message-in-txt); +} + +#back_to_bottom_button_container { + position: absolute; + bottom: var(--messagebar-size); + z-index: 1; + display: flex; + justify-content: center; + width: 100%; + height: 4em; + pointer-events: none; +} + +#back_to_bottom_button { + visibility: hidden; + margin: auto; + font: 0.875em emoji; + text-align: center; + width: 10em; + border-radius: 2em; + background-color: var(--jami-dark-blue); + color: #fff; + padding: 0.5em; + box-shadow: 2px 2px 4px black; + opacity: 1; + overflow: hidden; + white-space: nowrap; + transition: opacity .5s ease, width .2s ease, color .1s ease .2s; + pointer-events: all; +} + +#back_to_bottom_button:hover { + cursor: pointer; +} + +#back_to_bottom_button.fade { + opacity: 0; + width: 1em; + color: transparent; + transition: .2s opacity ease .1s, .2s width ease .1s, color .1s ease; +} + +#back_to_bottom_button.fade:hover { + cursor: context-menu; +} + +#messages { + position: relative; + z-index: 0; + width: 100%; + overflow: hidden; + height: auto; + padding-top: 0.5em; + opacity: 1; + transition: 0.5s opacity; +} + +#messages.fade { + opacity: 0; + transition: none; +} + +#messages:hover { + overflow-y: overlay; +} + +.last_message { + /* The last message gets a bigger bottom padding so that it is not + "glued" to the message bar. */ + padding-bottom: 1.5em !important; + margin-top: 4px; +} + +/* The container that envelopes the messagebar and file container */ +#send_inteface_container { + position: relative; + overflow: auto; + height: auto; + width: 100%; + bottom: 0; + padding: 0; + margin: 0; + z-index: 0; + display: table; +} + +/* General messages */ + +.internal_mes_wrapper { + max-width: 70%; + + display: flex; + flex-direction: column; + + /* If a message is smaller (in width) than the timestamp, do not fill + full width and pack message at the left. */ + align-items: flex-start; + align-content: flex-start; +} + +.message_out > .internal_mes_wrapper { + /* If message is in the outgoing direction, pack at the right. */ + align-items: flex-end; + align-content: flex-end; +} + +.message_wrapper { + max-width: calc(100% - 2em); + border-radius: 10px; + position: relative; + display: flex; + flex-direction: row; +} + +.message_type_data_transfer .message_wrapper { + display: flex; + flex-direction: column; + padding: 0; + width: 450px; + max-width: none; +} + +.message_type_audio_video_transfer { + display: flex; + flex-direction: column; + padding: 0; + width: auto !important; + max-width: none; +} + +.transfer_info_wrapper { + display: flex; + flex-direction: row; + padding-bottom: .8em; + padding-top: .8em; +} + +.message { + font: 0.875em emoji; + margin: 0; + display: flex; + justify-content: flex-start; + align-items: top; + overflow: hidden; + + /* enable selection (it is globally disabled in the body) */ + -webkit-user-select: auto; +} + +.message_in { + padding-left: 25%; +} + +.message_out { + padding-right: 25%; + + /* Message sent by the user should be displayed at the right side of + the screen. */ + flex-direction: row-reverse; +} + +.message_delivery_status { + margin: 10px 10px; + color: #A0A0A0; +} + +.message_sender { + display: none; +} + +.sender_image { + border-radius: 50%; + width: 35px; + height: 35px; +} + +div.last_message > span { + margin: 0px 10px 0px 10px; +} + +.message_out .message_wrapper { + border-top-right-radius: 0; + transform-origin: top right; + background-color: var(--message-out-bg); + color: var(--message-out-txt); +} + +.message_in .message_wrapper { + border-top-left-radius: 0; + transform-origin: top left; + background-color: var(--message-in-bg); + color: var(--message-in-txt); +} + +@-webkit-keyframes fade-in { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +.timestamp { + display: inline-flex; + justify-content: flex-start; + align-self: stretch; + color: var(--timestamp-color); + font-size: 10px; + padding: 5px; +} + +.timestamp_out { + flex-direction: row-reverse; +} + +.timestamp_action { + margin: auto; + padding: 0; + vertical-align: center; + opacity: 0; + transition: visibility 0.3s linear, opacity 0.3s linear; +} + +.message_type_contact .message_wrapper:hover .timestamp_action, +.message_type_call .message_wrapper:hover .timestamp_action { + opacity: 1; +} + +/* Ellipsis - dropdown menu */ + +input[type=checkbox] { + display: none; +} + +.menu_interaction +{ + margin: 5px; + padding: 10px; + padding-top: 0; + opacity: 0; + height: 20px; + transition: visibility 0.3s linear, opacity 0.3s linear; +} + +.message_type_call .menu_interaction +.message_type_contact .menu_interaction +{ + margin: auto; + padding: 0; + vertical-align: center; +} + +.message:hover .menu_interaction +{ + display: block; + opacity: 1; +} + + +.message_type_call .menu_interaction .dropdown +.message_type_contact .menu_interaction .dropdown +{ + margin-top: -17px; +} + +.dropdown { + display: none; + z-index: 1; + position: absolute; + background-color: #fff; + padding-top: 3px; + padding-bottom: 3px; +} + +.dropdown div +{ + color: #111; + padding: 10px; +} + +.dropdown div:hover +{ + background-color: #ddd; +} + +.showmenu:checked ~ .dropdown{ + display: block; +} + +/* Buttons */ + +.flat-button { + border: 0; + border-radius: 5px; + transition: all 0.3s ease; + color: #f9f9f9; + padding: 10px 20px 10px 20px; + vertical-align: middle; + cursor: pointer; + flex: 1; + padding: 0; +} + +.left_buttons { + align-self: center; + max-width: 90px; + padding-left: 1em; +} + +/* Status */ + +.status_circle { + fill: #A0A0A0; + -webkit-animation: circle-dance; + -webkit-animation-duration: 0.8s; + -webkit-animation-iteration-count: infinite; + -webkit-animation-direction: alternate; + -webkit-animation-timing-function: ease-in-out; +} + +.anim-first { + -webkit-animation-delay: 0.7s; +} + +.anim-second { + -webkit-animation-delay: 0.9s; +} + +.anim-third { + -webkit-animation-delay: 1.1s; +} + +@-webkit-keyframes circle-dance { + 0%,50% { + -webkit-transform: translateY(0); + fill: #A0A0A0; + } + 100% { + -webkit-transform: translateY(-8px); + fill: #000; + } +} + +.status-x { + stroke-dasharray: 12; +} + +/* Contact + Call interactions */ +.message_type_contact .message_wrapper, +.message_type_call .message_wrapper { + width: auto; + margin: auto; + display: flex; + flex-wrap: wrap; + background-color: var(--bg-color); + padding: 0; +} + +.message_type_contact .message_wrapper:before, +.message_type_call .message_wrapper:before { + display: none; +} + +.message_type_contact .text, +.message_type_call .text { + align-self: center; + font-size: 1.2em; + padding: 1em; +} + +/* file interactions */ + +.message_type_data_transfer .internal_mes_wrapper { + padding: 0.1em; + display: flex; + flex-wrap: wrap; +} + +.text-button { + border: none; + color: var(--text-color); + background-color: transparent; + font-size: 13px; + text-transform: uppercase; + font-weight: bold; + cursor: pointer; +} + + +.text-button:hover { + opacity: 0.5; +} + +.text-button-green { + color: var(--jami-green); +} + +.message_type_data_transfer .text { + text-align: left; + align-self: left; + padding: 0.3em; +} + +.truncate-ellipsis { + display: table; + table-layout: fixed; + width: 100%; + white-space: nowrap; +} + +.truncate-ellipsis > * { + display: table-cell; + overflow: hidden; + text-overflow: ellipsis; +} + +.message_type_data_transfer .filename { + cursor: pointer; + font-size: 1.1em; +} + +.message_in .informations { + color: var(--file-in-timestamp-color); + font-size: 0.8em; +} + +.message_out .informations { + color: var(--file-out-timestamp-color); + font-size: 0.8em; +} + +.message_progress_bar { + width: 100%; + height: 1em; + position: relative; + overflow: hidden; + background-color: #eee; + border-radius: 0; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.25) inset; +} + +.message_progress_bar > span { + display: inline; + height: 100%; + background-color: #01a2b8; + position: absolute; + overflow: hidden; +} + +/* text interactions */ + +.message_type_text .internal_mes_wrapper { + padding: 0.1em; +} + +.message_text { + max-width: 100%; +} + +.message_text pre { + display: inline; +} + +pre { + font : inherit; + font-family : inherit; + font-size : inherit; + font-style : inherit; + font-variant : inherit; + font-weight : inherit; + margin: 0; + padding: 0; +} + +/* Media interactions */ +.media_wrapper img { + max-width: 800px; + max-height: 700px; + margin: 2px 0 2px 0; + border-radius: 10px; +} + +.playVideo { + background-color: rgba(0, 0, 0, 0.6); + height: 50px; + width: 50px; + border-radius: 5px; + float: right; + position: absolute; + top: calc(50% - 25px); + left: calc(50% - 25px); + z-index: 3; +} + +.containerVideo { + width: 100%; + position: relative; +} + +.playVideo svg { + height: 40px; + width: 40px; + margin: 5px; +} + +/* Text interaction */ +.failure, +.sending { + margin: 10px 10px; + color: #A0A0A0; +} + +.no-audio-overlay { + overflow: visible; +} + +audio { + width: 16em; + align-self: center; +} + +.no-video-overlay { + overflow: visible; +} + +video { + width: 16em; + height: 9em; + align-self: center; +} + +/* classic screens */ +@media screen and (max-width: 1920px), screen and (max-height: 1080px) { + .message_in { + padding-left: 15%; + } + + .message_out { + padding-right: 15%; + } + + .message_type_contact, + .message_type_call { + padding: 0; + } + + .internal_mes_wrapper { + max-width: 60%; + } + + .media_wrapper img { + /* It is perfectly fine to specify max-widths in px when the + wrapper's max-width is in %, as long as the max-width in px + doesn't exceed the one in %. */ + max-width: 450px; + max-height: 450px; + } + + .menu_interaction + { + margin: 5px; + padding: 2px; + height: 10px; + font-size: 0.7em; + transition: visibility 0.3s linear,opacity 0.3s linear; + } +} + +/* lower resolutions */ +@media screen and (max-width: 1000px), screen and (max-height: 480px) { + .message_in { + padding-left: 0; + } + + .message_out { + padding-right: 0; + } + + .message_type_contact, + .message_type_call { + max-width: 100%; + } + + .internal_mes_wrapper { + max-width: 90%; + } + + /* Media interactions */ + .media_wrapper img { + max-width: 200px; + max-height: 200px; + } +} + +@media screen and (max-width: 550px) { + .message_type_data_transfer .message_wrapper { + width: 250px; + } + + #join_text { + font-size: 1.1em; + } + + #note_text { + font-size: .8em; + } +} + +/* Special case */ +@media screen and (max-width: 350px) { + .sender_image:not(#invite_image) { + display: none; + } + + /* File interactions */ + .message_type_data_transfer .left_buttons { + max-width: 100%; + } + + .message_type_data_transfer .text { + max-width: 100%; + padding-left: 0; + } + + .message_type_data_transfer .message_wrapper { + width: 200px; + } + + #join_text { + font-size: 1em; + } + + #note_text { + font-size: .8em; + } +} + +@media screen and (max-height: 640px) { + + .note_container { + opacity: 0; + transition: opacity 0.3s linear; + } +} + +@media screen and (max-height: 500px) { + + #invitation_rect { + background-color: transparent; + transition: background-color 0.3s; + box-shadow: 7px 7px 30px transparent; + transition: box-shadow 0.3s; + transform: translate(-50%, -95%); + transition: transform 0.8s; + } + + #invite_image, #quote_img { + opacity: 0; + transition: opacity 0.3s; + } +} + +.nav-right { + align-self: flex-end; +} + +.nav-left { + align-self: flex-start; +} + +#nav-contactid { + margin: 0px; + margin-left: 5px; + padding: 0px; + height: 100%; + font-family: emoji; + /* enable selection (it is globally disabled in the body) */ + -webkit-user-select: auto; + /* contactid field should take as much place as possible, but it should + also be the first one to shrink if necessary. */ + flex-grow: 2; + flex-shrink: 2; + min-width: 0; /* necessary for child to be able to shrink correctly */ + /* center vertically */ + display: flex; + align-items: center; +} + +#nav-contactid-wrapper { + width: 100%; +} + +#nav-contactid-alias { + font-size: 14px; + font-weight: bold; + margin-bottom: 3px; + width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +#nav-contactid-bestId { + font-size: 11px; + width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.oneEntry #nav-contactid-bestId { + display: none; +} + +.typing_message { + display: flex; + justify-content: flex-start; +} + +.typing_message .message_wrapper { + border-top-left-radius: 0; + transform-origin: top left; + background-color: var(--message-out-bg); + color: var(--message-out-txt); + margin-top: auto; + margin-bottom: auto; +} + +.typing-indicator { + width: auto; + border-radius: 50px; + padding: 0px; + display: table; + position: relative; + -webkit-animation: 2s bulge infinite ease-out; + animation: 2s bulge infinite ease-out; +} +.typing-indicator span { + height: 8px; + width: 8px; + float: left; + margin: 0 1px; + background-color: #003b4e; + display: block; + border-radius: 50%; + opacity: 0.4; +} +.typing-indicator span:nth-of-type(1) { + -webkit-animation: 1s blink infinite 0.3333s; + animation: 1s blink infinite 0.3333s; +} +.typing-indicator span:nth-of-type(2) { + -webkit-animation: 1s blink infinite 0.6666s; + animation: 1s blink infinite 0.6666s; +} +.typing-indicator span:nth-of-type(3) { + -webkit-animation: 1s blink infinite 0.9999s; + animation: 1s blink infinite 0.9999s; +} + +@-webkit-keyframes blink { + 50% { + opacity: 1; + } +} + +@keyframes blink { + 50% { + opacity: 1; + } +} +@-webkit-keyframes bulge { + 50% { + -webkit-transform: scale(1.05); + transform: scale(1.05); + } +} +@keyframes bulge { + 50% { + -webkit-transform: scale(1.05); + transform: scale(1.05); + } +} + +.preview_wrapper_in { + margin: 0px; + padding: 0px 0px; + box-sizing: border-box; + max-width: 300px; + min-width: 100px; + height: auto; + width: calc(20vw); + position: relative; + word-wrap: break-word; + overflow: hidden; + float: left; + border-bottom-right-radius: 20px; +} + +.preview_wrapper_out { + margin: 0px; + padding: 0px 0px; + box-sizing: border-box; + max-width: 300px; + min-width: 100px; + height: auto; + width: calc(20vw); + position: relative; + word-wrap: break-word; + overflow: hidden; + border-bottom-right-radius: 20px; +} + +.preview_container_link { + text-decoration: none; + display: inline-block; + border-bottom: none; + height: auto; + max-width: 300px; + width: inherit; + min-width: inherit; +} + +.preview_card_container { + font-family: emoji; + display: flex; + align-items: center; + max-width: 300px; + height: auto; + float: right; + width: inherit; + min-width: inherit; +} + +.message_wrapper_with_image_preview{ + border-bottom-left-radius: 0px !important; + border-bottom-right-radius: 0px !important; + margin-right: 0px; + margin-left: 0px; + width: calc(20vw); + max-width: 300px !important; + padding-right: 0px !important; + padding-left: 0px !important; + min-width: 100px; +} + +.message_wrapper_without_image_preview{ + border-bottom-left-radius: 0px !important; + border-bottom-right-radius: 0px !important; + width: calc(20vw); + max-width: 300px !important; + padding-right: 0px !important; + padding-left: 0px !important; + min-width: 100px; +} + +.msg_cell_with_preview{ + max-width: 300px; + padding-bottom: 0px; + width: calc(20vw); + min-width: 100px; +} + +.card_container_out { + border-radius: 20px; + height: auto; + width: inherit; + background-color: var(--preview-card-container-color); + min-width: inherit; +} + +.card_container_in { + border-radius: 20px; + height: auto; + width: inherit; + background-color: var(--preview-card-container-color); + min-width: inherit; +} + +.preview_image { + height: auto; + width: 101%; + right: 0px; + max-height: 200px; + background-color: var(--preview-image-background-color);; + object-fit: cover; + max-width: 300px; + min-width: inherit; +} + +.preview_text_container { + padding: 15px 20px; + height: auto; + background-color: var(--preview-text-container-color); + border-bottom-left-radius: 20px; + width: inherit; + border-bottom-right-radius: 20px +} + +.preview_card_title { + font-size: 0.875em emoji; + color: var(--preview-title-color); + width: 85%; + height: auto; + white-space: nowrap; + margin-top: 0px; + text-overflow: ellipsis; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.preview_card_subtitle { + font-size: 11px; + margin-top: 5px; + color: var(--preview-subtitle-color); + text-overflow: ellipsis; + overflow: hidden; + width: 85%; + height: auto; + display: -webkit-box; + -webkit-box-orient: vertical; + overflow: hidden; + -webkit-line-clamp: 2; +} + +.preview_card_link { + font-size: 11px; + color: var(--preview-url-color); + margin-top: 15px; + text-overflow: ellipsis; + overflow: hidden; + width: 85%; + height: 12px; +} + +.message_text_with_preview { + padding-left: 14px; + padding-right: 14px; +} + +.text_link{ + border-bottom: dotted 1px; +} diff --git a/src/libclient/web-chatview/chatview.html b/src/libclient/web-chatview/chatview.html new file mode 100644 index 0000000000000000000000000000000000000000..f2f50c38ae7de14bd8390752b4a5b624f9bde5ef --- /dev/null +++ b/src/libclient/web-chatview/chatview.html @@ -0,0 +1,161 @@ +<html> +<!-- Empty head might be needed for setSenderImage --> + +<head> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <meta charset="utf-8"> +</head> + +<body> + <div id="wrapperOfNavbar" class="navbar-wrapper"> + <div id="navbar"> + <div id="backButton" class="nav-button non-action-button nav-left" onmouseover="addBackButtonHoverProperty()" + onclick="backToWelcomeView()"> + <svg class="svgicon" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24"> + <path d="M0 0h24v24H0z" fill="none" /> + <path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z" /> + </svg> + </div> + <div id="nav-contactid" class="nav-left"> + <div id="nav-contactid-wrapper"> + <div id="nav-contactid-alias"></div> + <div id="nav-contactid-bestId"></div> + </div> + </div> + <div id="optionsButton" style="display:none" class="deactivated nav-button action-button nav-right" onclick="moreOptions()"> + <svg class="svgicon" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24"> + <path d="M0 0h24v24H0z" fill="none" /> + <path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z" /> + </svg> + </div> + <div id="placeAudioCallButton" class="nav-button action-button nav-right" onclick="placeAudioCall()"> + <svg class="svgicon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> + <path fill="none" d="M0 0h24v24H0z" /> + <path d="M20.01 15.38c-1.23 0-2.42-.2-3.53-.56-.35-.12-.74-.03-1.01.24l-1.57 1.97c-2.83-1.35-5.48-3.9-6.89-6.83l1.95-1.66c.27-.28.35-.67.24-1.02-.37-1.11-.56-2.3-.56-3.53 0-.54-.45-.99-.99-.99H4.19C3.65 3 3 3.24 3 3.99 3 13.28 10.73 21 20.01 21c.71 0 .99-.63.99-1.18v-3.45c0-.54-.45-.99-.99-.99z" /> + </svg> + </div> + <div id="placeCallButton" class="nav-button action-button nav-right" onclick="placeCall()"> + <svg class="svgicon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> + <path d="M0 0h24v24H0z" fill="none" /> + <path d="M17 10.5V7c0-.55-.45-1-1-1H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-3.5l4 4v-11l-4 4z" /> + </svg> + </div> + <div id="pluginsButton" style="display:none" class="nav-button action-button nav-right" onclick="openPluginHandlersList()"> + <svg class="svgicon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> + <path d="M0 0h24v24H0V0z" fill="none" /> + <path d="M20.5 11H19V7c0-1.1-.9-2-2-2h-4V3.5C13 2.12 11.88 1 10.5 1S8 2.12 8 3.5V5H4c-1.1 0-1.99.9-1.99 2v3.8H3.5c1.49 0 2.7 1.21 2.7 2.7s-1.21 2.7-2.7 2.7H2V20c0 1.1.9 2 2 2h3.8v-1.5c0-1.49 1.21-2.7 2.7-2.7s2.7 1.21 2.7 2.7V22H17c1.1 0 2-.9 2-2v-4h1.5c1.38 0 2.5-1.12 2.5-2.5S21.88 11 20.5 11z"/> + </svg> + </div> + <div id="addToConversationsButton" class="nav-button action-button nav-right" onclick="addToConversations()"> + <svg class="svgicon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> + <path d="M0 0h24v24H0z" fill="none" /> + <path d="M15 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm-9-2V7H4v3H1v2h3v3h2v-3h3v-2H6zm9 4c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" /> + </svg> + </div> + <div id="unbanButton" class="nav-button action-critical-button nav-right" onclick="addBannedContact()"> + <svg class="svgicon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> + <path fill="none" d="M0 0h24v24H0V0z" /> + <circle cx="15" cy="8" r="4" /> + <path d="M23 20v-2c0-2.3-4.1-3.7-6.9-3.9l6 5.9h.9zm-11.6-5.5C9.2 15.1 7 16.3 7 18v2h9.9l4 4 1.3-1.3-21-20.9L0 3.1l4 4V10H1v2h3v3h2v-3h2.9l2.5 2.5zM6 10v-.9l.9.9H6z" /> + </svg> + </div> + </div> + </div> + <div id="container"> + <div id="invitation" class="column"> + <div id="invitation_text_container" class="note_container"> + <div id="invitation_text"></div> + </div> + + <div id="invitation_rect"> + <div id="invite_image"></div> + <div id="quote_img_wrapper"> + <svg width="47px" height="30px" viewBox="0 0 47 30" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <g id="CONVERSATION-À-PLUS" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" opacity="0.7"> + <g id="04_JAMI_CONV_Invitation" transform="translate(-702.000000, -310.000000)" fill="#1AB6FF" fill-rule="nonzero"> + <g id="noun_Quote_3101618" transform="translate(702.000000, 310.000000)"> + <path d="M9.24003238,27.2740291 C8.58821922,28.5250019 9.49495696,30 10.9415649,30 C11.5043326,30 12.0360615,29.7625927 12.4039467,29.349732 C14.4647143,27.033648 21.2225055,18.9494095 21.9282548,11.8341297 C21.9725231,11.4475374 22,11.0554933 22,10.6570059 C22,10.3333588 21.9811732,10.0458928 21.9542052,9.77527819 C21.4499531,3.84207854 15.9418521,-0.717231757 9.52090737,0.0936206879 C4.60101556,0.715637692 0.635182818,4.63161885 0.0734328381,9.40801556 C-0.615525018,15.279757 3.62660323,20.3376721 9.30414515,21.188175 C10.1823883,21.3210042 10.7538061,22.1482124 10.5085493,22.976412 L9.24003238,27.2740291 Z" id="Path"></path> + <path d="M34.2399734,27.2740291 C33.588666,28.5250019 34.4948991,30 35.9415138,30 C36.504284,30 37.0355066,29.7625927 37.4039023,29.349732 C39.4651882,27.033648 46.2225019,18.9494095 46.9287633,11.8341297 C46.972523,11.4475374 47,11.0554933 47,10.6570059 C47,10.3333588 46.9811731,10.0458928 46.954205,9.77527819 C46.4499506,3.84207854 40.9418241,-0.717231757 34.5203408,0.0936206879 C29.6004263,0.715637692 25.6345752,4.63161885 25.0733314,9.40851119 C24.3848792,15.279757 28.6270271,20.3376721 34.3045953,21.188175 C35.1828425,21.3210042 35.7542629,22.1482124 35.509005,22.976412 L34.2399734,27.2740291 Z" id="Path"></path> + </g> + </g> + </g> + </svg> + </div> + <div id="invite_text"> + <div id="join_text"></div> + <div id="note_text"></div> + <div id="actions"> + <button id="blockButton" class="text-button" onclick="blockConversation()"> + </button> + <button id="refuseButton" class="text-button" onclick="refuseInvitation()"> + </button> + <button id="acceptButton" class="text-button text-button-green" onclick="acceptInvitation()"> + </button> + </div> + </div> + </div> + + <div id="invitation_note_container" class="note_container"> + <div id="invitation_note"></div> + </div> + </div> + <div id="messages" onscroll="onScrolled()"></div> + + <div id="typing_indicator_container"></div> + + <div id="back_to_bottom_button_container"> + <div id="back_to_bottom_button" onclick="back_to_bottom()">Jump to latest ▼ +</div> + </div> + + <div id="send_inteface_container" onresize="updateBackToBottomContainer()"> + <div id="sendMessage"> + <div id="sendFileButton" class="nav-button action-button" onclick="selectFileToSend()"> + <svg class="svgicon" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve"> + <path d="M16.1,5.6c-0.3,0-0.6,0.3-0.6,0.6v11.2c0,1.9-1.6,3.5-3.5,3.5c-1.9,0-3.5-1.6-3.5-3.5V5.5c0-1.2,1-2.3,2.3-2.3 s2.3,1,2.3,2.3v10.6c0,0.6-0.5,1-1,1s-1-0.5-1-1V6.7c0-0.3-0.3-0.6-0.6-0.6c-0.3,0-0.6,0.3-0.6,0.6v9.4c0,1.2,1,2.2,2.2,2.2 s2.2-1,2.2-2.2V5.5c0-1.9-1.6-3.5-3.5-3.5S7.3,3.6,7.3,5.5v11.8c0,2.6,2.1,4.7,4.7,4.7c2.6,0,4.7-2.1,4.7-4.7V6.2 C16.7,5.8,16.4,5.6,16.1,5.6z"/> + </svg> + </div> + <div id="audioRecordButton" class="action-button nav-button" onclick="audioRecord()"> + <svg class="svgicon" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve"> + <g> + <path d="M19.1,4.9C17.2,3,14.7,2,12,2S6.8,3,4.9,4.9S2,9.3,2,12s1,5.2,2.9,7.1S9.3,22,12,22h10V12C22,9.3,21,6.8,19.1,4.9z M20.6,20.6H12c-2.3,0-4.4-0.9-6.1-2.5c-1.6-1.6-2.5-3.8-2.5-6.1s0.9-4.4,2.5-6.1C7.6,4.3,9.7,3.4,12,3.4s4.4,0.9,6.1,2.5 c1.6,1.6,2.5,3.8,2.5,6.1V20.6z"/> + <path d="M15,10.3c-0.1,0.1-0.2,0.2-0.2,0.4v1.4c0,1.4-1.1,2.5-2.5,2.5s-2.5-1.1-2.5-2.5v-1.4c0-0.1-0.1-0.3-0.2-0.4 c-0.1-0.1-0.2-0.2-0.4-0.2l0,0c-0.2,0-0.3,0.1-0.4,0.2c-0.1,0.1-0.2,0.2-0.2,0.4v1.4c0,1.8,1.3,3.3,3.1,3.6v0.5h-0.9 c-0.3,0-0.5,0.2-0.5,0.5s0.2,0.5,0.5,0.5h2.8c0.3,0,0.5-0.2,0.5-0.5s-0.2-0.5-0.5-0.5h-0.9v-0.5c1.7-0.3,3.1-1.8,3.1-3.6v-1.4 c0-0.1-0.1-0.3-0.2-0.4C15.5,10.2,15.2,10.1,15,10.3z M9.2,10.4L9.2,10.4L9.2,10.4L9.2,10.4L9.2,10.4z"/> + </g> + <g> + <path d="M12.3,13.9c-1,0-1.8-0.8-1.8-1.8V9c0-1,0.8-1.8,1.8-1.8S14.1,8,14.1,9v3.2C14.1,13.2,13.3,13.9,12.3,13.9z M12.3,8.4 c-0.3,0-0.6,0.2-0.6,0.6v3.2c0,0.3,0.2,0.6,0.6,0.6c0.3,0,0.6-0.2,0.6-0.6V9C12.9,8.7,12.6,8.4,12.3,8.4z"/> + </g> + </svg> + </div> + <div id="videoRecordButton" class="nav-button action-button" onclick="videoRecord()"> + <svg class="svgicon" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve"> + <g> + <path d="M22,22H12c-2.7,0-5.2-1-7.1-2.9C3,17.2,2,14.7,2,12c0-2.7,1-5.2,2.9-7.1S9.3,2,12,2c2.7,0,5.2,1,7.1,2.9 C21,6.8,22,9.3,22,12V22z M12,3.4c-2.3,0-4.4,0.9-6.1,2.5C4.3,7.6,3.4,9.7,3.4,12c0,2.3,0.9,4.4,2.5,6.1c1.6,1.6,3.8,2.5,6.1,2.5 h8.6V12c0-2.3-0.9-4.4-2.5-6.1C16.4,4.3,14.3,3.4,12,3.4z"/> + </g> + <g transform="translate(7.000000, 9.000000)"> + <path d="M7.1,7.7H0.4c-0.8,0-1.2-0.5-1.2-1V0.3c0-0.4,0.4-0.9,1.1-1l6.7,0c0.7,0,1.1,0.5,1.1,1v0.6l1.1-0.6C9.6,0,10,0,10.3,0.2 c0.2,0.1,0.5,0.3,0.5,0.8v5c0,0.5-0.3,0.8-0.5,0.9C10,7,9.6,7,9.3,6.8L8.2,6.2v0.6C8.2,7.2,7.8,7.7,7.1,7.7z M0.5,6.4l6.4,0V5.1 c0-0.2,0.1-0.4,0.3-0.6c0.2-0.1,0.4-0.1,0.6,0l1.6,0.9V1.6L7.9,2.5c-0.2,0.1-0.4,0.1-0.6,0C7,2.4,6.9,2.2,6.9,1.9V0.6l-6.4,0V6.4 z M10,5.7L10,5.7C10,5.7,10,5.7,10,5.7z"/> + </g> + </svg> + </div> + <textarea id="message" autofocus onkeyup="grow_text_area()" onkeydown="process_messagebar_keydown()" + dir="auto" rows="1"></textarea> + <div id="emojiButton" class="action-button nav-button"> + <svg class="svgicon" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve"> + <path d="M12,2.1c-5.4,0-9.9,4.4-9.9,9.9s4.4,9.9,9.9,9.9s9.9-4.4,9.9-9.9S17.4,2.1,12,2.1z M12,20.7c-4.8,0-8.7-3.9-8.7-8.7 S7.2,3.3,12,3.3s8.7,3.9,8.7,8.7S16.8,20.7,12,20.7z"/> + <path d="M7.4,13.3c-0.2,0-0.4,0.1-0.5,0.2c-0.1,0.1-0.1,0.3-0.1,0.5c0,0.1,0.1,0.3,0.2,0.4c1.4,1,3.1,1.5,4.9,1.5s3.4-0.5,4.9-1.5 c0.1-0.1,0.2-0.2,0.3-0.4c0-0.2,0-0.3-0.1-0.4c-0.2-0.3-0.5-0.3-0.8-0.1c-1.2,0.8-2.7,1.3-4.2,1.3s-3-0.4-4.2-1.3 C7.7,13.3,7.5,13.3,7.4,13.3z"/> + <path d="M8,8.9c-0.4,0-0.8,0.3-0.8,0.8c0,0.4,0.3,0.8,0.8,0.8s0.8-0.3,0.8-0.8C8.8,9.2,8.5,8.9,8,8.9z"/> + <path d="M16,8.9c-0.4,0-0.8,0.4-0.8,0.8c0,0.5,0.3,0.8,0.8,0.8c0.4,0,0.8-0.3,0.8-0.8C16.8,9.2,16.4,8.9,16,8.9z"/> + </svg> + </div> + <div id="sendButton" class="nav-button action-button" onclick="sendMessage();"> + <svg class="svgicon" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve"> + <g transform="translate(2.000000, 3.000000)"> + <path id="Shape" d="M20,9c0-0.3-0.2-0.5-0.4-0.6L1.1-0.2C0.8-0.3,0.4-0.2,0.2,0s-0.3,0.6-0.1,0.9L4,9l-3.9,8.1 C-0.1,17.4,0,17.8,0.2,18c0.2,0.2,0.6,0.3,0.9,0.2l18.5-8.5C19.8,9.6,20,9.3,20,9L20,9z M17.4,9l-15,6.9l3.2-6.5 c0.1-0.2,0.1-0.5,0-0.7L2.4,2.1L17.4,9z"/> + </g> + </svg> + </div> + </div> + </div> + <div id="data_transfer_send_container"></div> + </div> +</body> +</html> diff --git a/src/libclient/web-chatview/chatview.js b/src/libclient/web-chatview/chatview.js new file mode 100644 index 0000000000000000000000000000000000000000..65f6b83241b87dacb7bd93ad8a829ca4ebf86ec7 --- /dev/null +++ b/src/libclient/web-chatview/chatview.js @@ -0,0 +1,2793 @@ +"use strict" + +/* Constants used at several places */ +// scrollDetectionThresh represents the number of pixels a user can scroll +// without disabling the automatic go-back-to-bottom when a new message is +// received +const scrollDetectionThresh = 70 +// printHistoryPart loads blocks of messages. Each block contains +// scrollBuffer messages +const scrollBuffer = 20 +// The first time a conversation is loaded, the lazy loading system makes +// sure at least initialScrollBufferFactor screens of messages are loaded +const initialScrollBufferFactor = 3 +// Some signal like the onscrolled signals are debounced so that the their +// assigned function isn't fired too often +const debounceTime = 200 + +/* Buffers */ +// current index in the history buffer +var historyBufferIndex = 0 +// buffer containing the conversation's messages +var historyBuffer = [] + +// If we use qt +var use_qt = false + +var is_swarm = false + +if (navigator.userAgent == "jami-qt") { + use_qt = true +} + +/* We retrieve refs to the most used navbar and message bar elements for efficiency purposes */ +/* NOTE: use getElementById when possible (more readable and efficient) */ +const addToConversationsButton = document.getElementById("addToConversationsButton") +const placeAudioCallButton = document.getElementById("placeAudioCallButton") +const backButton = document.getElementById("backButton") +const placeCallButton = document.getElementById("placeCallButton") +const pluginsButton = document.getElementById("pluginsButton") +const unbanButton = document.getElementById("unbanButton") +const acceptButton = document.getElementById("acceptButton") +const refuseButton = document.getElementById("refuseButton") +const blockButton = document.getElementById("blockButton") + +const callButtons = document.getElementById("callButtons") +const sendButton = document.getElementById("sendButton") +sendButton.style.display = "none" +const optionsButton = document.getElementById("optionsButton") +const backToBottomBtn = document.getElementById("back_to_bottom_button") +const backToBottomBtnContainer = document.getElementById("back_to_bottom_button_container") +const sendFileButton = document.getElementById("sendFileButton") +const videoRecordButton = document.getElementById("videoRecordButton") +const audioRecordButton = document.getElementById("audioRecordButton") +const aliasField = document.getElementById("nav-contactid-alias") +const bestIdField = document.getElementById("nav-contactid-bestId") +const idField = document.getElementById("nav-contactid") +const messageBar = document.getElementById("sendMessage") +const messageBarInput = document.getElementById("message") +const addToConvButton = document.getElementById("addToConversationsButton") +const invitation = document.getElementById("invitation") +invitation.style.display = "none" + +const inviteImage = document.getElementById("invite_image") + +const navbar = document.getElementById("navbar") +const emojiBtn = document.getElementById("emojiButton") +const invitationText = document.getElementById("invitation_text") +const joinText = document.getElementById("join_text") +const noteText = document.getElementById("note_text") + +var messages = document.getElementById("messages") +var sendContainer = document.getElementById("data_transfer_send_container") +var wrapperOfNavbar = document.getElementById("wrapperOfNavbar") + +/* States: allows us to avoid re-doing something if it isn't meaningful */ +var displayLinksEnabled = true +var hoverBackButtonAllowed = true +var hasInvitation = false +var isTemporary = false +var isBanned = false +var isAccountEnabled = true +var isInitialLoading = false +var imagesLoadingCounter = 0 +var canLazyLoad = false + +// ctrl + click on link will crash QtWebEngineProcess +document.body.onclick = function(e) { + if (e.ctrlKey) { + return false + } +} + +// same for mouse middle button +document.body.onauxclick = function(e) { + if (e.which === 2) { + return false + } +} + +/* String sipmle format prototype*/ +String.prototype.format = function() { + var a = this + for (var k in arguments) { + a = a.replace("{" + k + "}", arguments[k]) + } + return a +} + +/* Set the default target to _self and handle with QWebEnginePage::acceptNavigationRequest */ +var linkifyOptions = {} +if (use_qt) { + messageBarInput.onpaste = pasteKeyDetected + linkifyOptions = { + attributes: null, + className: "linkified", + defaultProtocol: "http", + events: null, + format: function (value, type) { + return value + }, + formatHref: function (href, type) { + return href + }, + ignoreTags: [], + nl2br: false, + tagName: "a", + target: { + url: "_self" + }, + validate: true + } + new QWebChannel(qt.webChannelTransport, function (channel) { + window.jsbridge = channel.objects.jsbridge + + // connect to a signal + window.jsbridge.setSendMessageContentRequest.connect(function(content) { + setSendMessageContent(content) + }) + }) +} + +/* i18n manager */ +var i18n = null + +/* i18n string data for client-qt*/ +var i18nStringData + +/* exported init_i18n */ +function init_i18n(data) { + if (use_qt) { + window.jsbridge.parseI18nData(function(stringData) { + i18nStringData = stringData + reset_message_bar_input("") + set_titles() + }) + } else { + if (data === undefined) { + i18n = new Jed({ locale_data: { "messages": { "": {} } } }) // eslint-disable-line no-undef + } else { + var domain = { + "" : { + // Domain name + "domain" : "messages", + } + } + for (var key in data) { + domain[key] = [data[key]] + } + i18n = new Jed({ locale_data: { "messages": domain } }) + } + reset_message_bar_input("") + set_titles() + } +} + +/* exported init_picker */ +function init_picker(dark) { + const picker = new EmojiButton({ + theme: dark? "dark" : "light" + }) + picker.on("emoji", emoji => { + messageBarInput.value += emoji.emoji + }) + emojiBtn.addEventListener("click", () => { + picker.togglePicker(emojiBtn) + }) +} + +/* exported set_is_swarm */ +function set_is_swarm(value) { + is_swarm = value +} + +function set_titles() { + if (use_qt){ + backButton.title = i18nStringData["Hide chat view"] + placeCallButton.title = i18nStringData["Place video call"] + pluginsButton.title = i18nStringData["Show available plugins"] + placeAudioCallButton.title = i18nStringData["Place audio call"] + addToConversationsButton.title = i18nStringData["Add to conversations"] + unbanButton.title = i18nStringData["Unban contact"] + sendButton.title = i18nStringData["Send"] + optionsButton.title = i18nStringData["Options"] + backToBottomBtn.innerHTML = `${i18nStringData["Jump to latest"]} ▼` + sendFileButton.title = i18nStringData["Send file"] + emojiBtn.title = i18nStringData["Add emoji"] + videoRecordButton.title = i18nStringData["Leave video message"] + audioRecordButton.title = i18nStringData["Leave audio message"] + acceptButton.title = i18nStringData["Accept"] + refuseButton.title = i18nStringData["Refuse"] + blockButton.title = i18nStringData["Block"] + acceptButton.innerHTML = i18nStringData["Accept"] + refuseButton.innerHTML = i18nStringData["Refuse"] + blockButton.innerHTML = i18nStringData["Block"] + } else { + backButton.title = i18n.gettext("Hide chat view") + placeCallButton.title = i18n.gettext("Place video call") + pluginsButton.title = i18n.gettext("Show available plugins") + placeAudioCallButton.title = i18n.gettext("Place audio call") + addToConversationsButton.title = i18n.gettext("Add to conversations") + unbanButton.title = i18n.gettext("Unban contact") + sendButton.title = i18n.gettext("Send") + optionsButton.title = i18n.gettext("Options") + backToBottomBtn.innerHTML = `${i18n.gettext("Jump to latest")} ▼` + sendFileButton.title = i18n.gettext("Send file") + emojiBtn.title = i18n.gettext("Add emoji") + videoRecordButton.title = i18n.gettext("Leave video message") + audioRecordButton.title = i18n.gettext("Leave audio message") + acceptButton.title = i18n.gettext("Accept") + refuseButton.title = i18n.gettext("Refuse") + blockButton.title = i18n.gettext("Block") + acceptButton.innerHTML = i18n.gettext("Accept") + refuseButton.innerHTML = i18n.gettext("Refuse") + blockButton.innerHTML = i18n.gettext("Block") + } +} + +function reset_message_bar_input(name) { + messageBarInput.placeholder = use_qt ? + i18nStringData["Write to {0}"].format(name) : + i18n.gettext("Write to {0}").format(name) +} + +function onScrolled_() { + if (!canLazyLoad) + return + // back to bottom button + if(messages.scrollTop >= messages.scrollHeight - messages.clientHeight - scrollDetectionThresh) { + // fade out + if (!backToBottomBtn.classList.contains("fade")) { + backToBottomBtn.classList.add("fade") + backToBottomBtn.removeAttribute("onclick") + } + } else { + // fade in + if (backToBottomBtn.classList.contains("fade")) { + backToBottomBtn.style.visibility = "visible" + backToBottomBtnContainer.style.visibility = "visible" + backToBottomBtn.classList.remove("fade") + backToBottomBtn.onclick = back_to_bottom + } + } + + if (messages.scrollTop === 0) { + if (use_qt) { + window.jsbridge.loadMessages(scrollBuffer) + } else { + window.prompt(`LOAD_MESSAGES:${scrollBuffer}`) + } + } +} + +const debounce = (fn, time) => { + let timeout + + return function () { + const functionCall = () => fn.apply(this, arguments) + + clearTimeout(timeout) + timeout = setTimeout(functionCall, time) + } +} + +/* exported onScrolled */ +var onScrolled = debounce(onScrolled_, debounceTime) + +/** + * Generic wrapper. Execute passed function keeping scroll position identical. + * + * @param func function to execute + * @param args parameters as array + */ +function exec_keeping_scroll_position(func, args) { + var atEnd = messages.scrollTop >= messages.scrollHeight - messages.clientHeight - scrollDetectionThresh + func(...args) + if (atEnd) { + messages.scrollTop = messages.scrollHeight + } +} + +/** + * Reset scrollbar at a given position. + * @param scroll position at which the scrollbar should be set. + * Here position means the number of pixels scrolled, + * i.e. scroll = 0 resets the scrollbar at the bottom. + */ +function back_to_scroll(scroll) { + messages.scrollTop = messages.scrollHeight - scroll +} + +/** + * Reset scrollbar at bottom. + */ +function back_to_bottom() { + back_to_scroll(0) +} + +/** + * Update common frame between conversations. + * + * Whenever the current conversation is switched, information from the navbar + * and message bar have to be updated to match new contact. This function + * handles most of the required work (except the showing/hiding the invitation, + * which is handled by showInvitation()). + * + * @param accountEnabled whether account is enabled or not + * @param banned whether contact is banned or not + * @param temporary whether contact is temporary or not + * @param alias + * @param bestId + */ +/* exported update_chatview_frame */ +function update_chatview_frame(accountEnabled, banned, temporary, bestname, bestid) { + /* This function updates lots of things in the navbar and we don't want to + trigger that many DOM updates. Instead set display to none so DOM is + updated only once. */ + navbar.style.display = "none" + + hoverBackButtonAllowed = true + + aliasField.innerHTML = (bestname ? bestname : bestid) + + if (bestname) { + bestIdField.innerHTML = bestid + idField.classList.remove("oneEntry") + } else { + idField.classList.add("oneEntry") + } + + if (isAccountEnabled !== accountEnabled) { + isAccountEnabled = accountEnabled + hideMessageBar(!accountEnabled) + hideControls(!accountEnabled) + } + + if (isBanned !== banned) { + isBanned = banned + hideMessageBar(banned) + + if (banned) { + // contact is banned. update navbar and states + navbar.classList.add("onBannedState") + } else { + navbar.classList.remove("onBannedState") + } + } else if (isTemporary !== temporary) { + isTemporary = temporary + if (temporary) { + addToConvButton.style.display = "flex" + messageBarInput.placeholder = use_qt ? + i18nStringData["Note: an interaction will create a new contact."] : + i18n.gettext("Note: an interaction will create a new contact.") + } else { + addToConvButton.style.display = "" + } + } + + if (!temporary) { + reset_message_bar_input(bestname ? bestname : bestid) + } + + navbar.style.display = "" +} + + +/** + * Hide or show invitation to a conversation. + * + * Invitation is hidden if no bestId is passed. + * Otherwise, invitation div is updated. + * + * @param bestName + * @param bestId + * @param isSyncing + */ +/* exported showInvitation */ +function showInvitation(bestName, bestId, isSyncing) { + if (!bestId) { + if (hasInvitation) { + hasInvitation = false + invitation.style.display = "none" + messages.style.visibility = "visible" + } + messageBar.style.visibility = "visible" + } else { + if (!inviteImage.classList.contains("sender_image")) { + inviteImage.classList.add("sender_image") + } + if (use_qt) { + if (!inviteImage.classList.contains(`sender_image_${bestId}`)) { + inviteImage.classList.add(`sender_image_${bestId}`) + } + } else { + const className = `sender_image_${bestId}`.replace(/@/g, "_").replace(/\./g, "_") + if (!inviteImage.classList.contains(className)) { + inviteImage.classList.add(className) + } + } + invitationText.innerHTML = (bestName ? bestName : bestId) + + " " + + (use_qt + ? i18nStringData["has sent you a conversation request."] + : i18n.gettext("has sent you a conversation request.")) + + "<br/>" + + var joinTextValue = (isSyncing ? + "You have accepted the conversation request." : + "Hello, would you like to join the conversation?") + joinText.innerHTML = (use_qt ? + i18nStringData[joinTextValue] : + i18n.gettext(joinTextValue)) + + "<br/>" + + noteText.innerHTML = (use_qt ? + i18nStringData["We are waiting for another device to synchronize the conversation."] : + i18n.gettext("We are waiting for another device to synchronize the conversation.")) + + "<br/>" + + messages.style.visibility = "hidden" + hasInvitation = true + + invitation.style.display = "flex" + invitation.style.visibility = "visible" + + var actions = document.getElementById("actions") + var quote_img = document.getElementById("quote_img_wrapper") + if (isSyncing) { + actions.style.visibility = "collapse" + invitationText.style.visibility = "hidden" + quote_img.style.visibility = "collapse" + noteText.style.visibility = "visible" + } else { + actions.style.visibility = "visible" + invitationText.style.visibility = "visible" + quote_img.style.visibility = "visible" + noteText.style.visibility = "collapse" + } + } +} + +/** + * Hide or show navbar, and update body top padding accordingly. + * + * @param isVisible whether navbar should be displayed or not + */ +/* exported displayNavbar */ +function displayNavbar(isVisible) { + if (isVisible) { + navbar.classList.remove("hiddenState") + document.body.style.setProperty("--navbar-size", undefined) + } else { + navbar.classList.add("hiddenState") + document.body.style.setProperty("--navbar-size", "0") + } +} + +/** + * Hide or show record controls, and update body top padding accordingly. + * + * @param isVisible whether navbar should be displayed or not + */ +/* exported displayRecordControls */ +function displayRecordControls(isVisible) { + if (isVisible) { + audioRecordButton.classList.remove("hiddenState") + videoRecordButton.classList.remove("hiddenState") + } else { + audioRecordButton.classList.add("hiddenState") + videoRecordButton.classList.add("hiddenState") + } +} + +/** + * Hide or show plugin controls, and update body top padding accordingly. + * + * @param isVisible whether navbar should be displayed or not + */ +/* exported displayPluginControl */ +function displayPluginControl(isVisible) { + if (isVisible) { + pluginsButton.style.removeProperty("display") + } else { + pluginsButton.style.setProperty("display", "none") + } +} + + +/** + * Hide or show message bar, and update body bottom padding accordingly. + * + * @param hide whether message bar should be displayed or not + */ +/* exported hideMessageBar */ +function hideMessageBar(hide) { + if (hide) { + messageBar.classList.add("hiddenState") + document.body.style.setProperty("--messagebar-size", "0") + } else { + messageBar.classList.remove("hiddenState") + document.body.style.removeProperty("--messagebar-size") + } +} + +/** + * Hide or show call buttons + * + * @param hide whether the buttons should be hidden + */ +function hideControls(hide) { + if (hide) { + placeAudioCallButton.style.display = "none" + placeCallButton.style.display = "none" + } else { + placeAudioCallButton.style.display = "" + placeCallButton.style.display = "" + } +} + +/* exported setDisplayLinks */ +function setDisplayLinks(display) { + displayLinksEnabled = display +} + +/** + * This event handler dynamically resizes the message bar depending on the amount of + * text entered, while adjusting the body paddings so that that the message bar doesn't + * overlap messages when it grows. + */ +/* exported grow_text_area */ +function grow_text_area() { + exec_keeping_scroll_position(function () { + var old_height = window.getComputedStyle(messageBar).height + messageBarInput.style.height = "auto" /* <-- necessary, no clue why */ + messageBarInput.style.height = messageBarInput.scrollHeight + "px" + var new_height = window.getComputedStyle(messageBar).height + + var msgbar_size = window.getComputedStyle(document.body).getPropertyValue("--messagebar-size") + var total_size = parseInt(msgbar_size) + parseInt(new_height) - parseInt(old_height) + + document.body.style.setProperty("--messagebar-size", total_size.toString() + "px") + + if (use_qt) { + window.jsbridge.onComposing(messageBarInput.value.length !== 0) + } else { + window.prompt(`ON_COMPOSING:${messageBarInput.value.length !== 0}`) + } + }, []) + checkSendButton() +} + +/** + * This event handler processes keydown events from the message bar. When pressed key is + * the enter key, send the message unless shift or control was pressed too. + * + * @param key the pressed key + */ +/* exported process_messagebar_keydown */ +function process_messagebar_keydown(key) { + key = key || event + var map = {} + + map[key.keyCode] = key.type == "keydown" + if (key.ctrlKey && map[13]) { + messageBarInput.value += "\n" + } + if (key.ctrlKey || key.shiftKey) { + return true + } + if (map[13]) { + sendMessage() + key.preventDefault() + } + return true +} + +/* exported clearSenderImages */ +function clearSenderImages() { + var styles = document.head.querySelectorAll("style"), + i = styles.length + + while (i--) { + document.head.removeChild(styles[i]) + } +} + +/** + * This event handler adds the hover property back to the "back to welcome view" + * button. + * + * This is a hack. It needs some explanations. + * + * Problem: Whenever the "back to welcome view" button is clicked, the webview + * freezes and the GTK ring welcome view is displayed. While the freeze + * itself is perfectly fine (probably necessary for good performances), this + * is a big problem for us when the user opens a chatview again: Since the + * chatview was freezed, the back button has «remembered» the hover state and + * still displays the blue background for a small instant. This is a very bad + * looking artefact. + * + * In order to counter this problem, we introduced the following evil mechanism: + * Whenever a user clicks on the "back to welcome view" button, the hover + * property is disabled. The hover property stays disabled until the user calls + * this event handler by hover-ing the button. + */ +/* exported addBackButtonHoverProperty */ +function addBackButtonHoverProperty() { + if (hoverBackButtonAllowed) { + backButton.classList.add("non-action-button") + } +} + +/** + * Disable or enable textarea. + * + * @param isDisabled whether message bar should be enabled or disabled + */ +/* exported disableSendMessage */ +function disableSendMessage(isDisabled) { + messageBarInput.disabled = isDisabled +} + +/* + * Update timestamps messages. + */ +function updateView() { + updateTimestamps(messages) +} + +setInterval(updateView, 60000) + +/* exported addBannedContact */ +function addBannedContact() { + window.prompt("UNBLOCK") +} + +/* exported addToConversations */ +function addToConversations() { + window.prompt("ADD_TO_CONVERSATIONS") +} + +/* exported placeCall */ +function placeCall() { + window.prompt("PLACE_CALL") +} + +/* exported placeAudioCall */ +function placeAudioCall() { + window.prompt("PLACE_AUDIO_CALL") +} + +/* exported backToWelcomeView */ +function backToWelcomeView() { + backButton.classList.remove("non-action-button") + hoverBackButtonAllowed = false + window.prompt("CLOSE_CHATVIEW") +} + +function openPluginHandlersList() { + var rect = pluginsButton.getBoundingClientRect() + if (!use_qt) { + window.prompt(`LIST_PLUGIN_HANDLERS:${rect.left + rect.width / 2}x${rect.bottom}`) + } +} + +/** + * Transform a date to a string group like "1 hour ago". + * + * @param date + */ +function formatDate(date) { + const seconds = Math.floor((new Date() - date) / 1000) + var interval = Math.floor(seconds / (3600 * 24)) + + if (use_qt) { + if (interval > 5) + return date.toLocaleDateString() + if (interval > 1) + return "\u200E " + i18nStringData["%d days ago"].format(interval) + if (interval === 1) + return "\u200E " + i18nStringData["one day ago"] + + interval = Math.floor(seconds / 3600) + if (interval > 1) + return "\u200E " + i18nStringData["%d hours ago"].format(interval) + if (interval === 1) + return "\u200E " + i18nStringData["one hour ago"] + + interval = Math.floor(seconds / 60) + if (interval > 1) + return "\u200E " + i18nStringData["%d minutes ago"].format(interval) + return i18nStringData["just now"] + } else { + if (interval > 5) { + return date.toLocaleDateString() + } + + if (interval > 1) { + return i18n.sprintf(i18n.gettext("%d days ago"), interval) + } + if (interval === 1) { + return i18n.gettext("one day ago") // what about "yesterday"? + } + + interval = Math.floor(seconds / 3600) + if (interval > 1) { + return i18n.sprintf(i18n.gettext("%d hours ago"), interval) + } + if (interval === 1) { + return i18n.gettext("one hour ago") + } + + interval = Math.floor(seconds / 60) + if (interval > 1) { + return i18n.sprintf(i18n.gettext("%d minutes ago"), interval) + } + + return i18n.gettext("just now") + } +} + +/** + * Send content of message bar + */ +function sendMessage() { + if (use_qt) { + //send image in sendContainer + var data_to_send = sendContainer.innerHTML + var imgSrcExtract = new RegExp("<img src=\"(.*?)\">", "g") + var fileSrcExtract = new RegExp("<div class=\"file_wrapper\" data-path=\"(.*?)\">", "g") + + var img_src + while ((img_src = imgSrcExtract.exec(data_to_send)) !== null) { + window.jsbridge.sendImage(img_src[1]) + } + + var file_src + while ((file_src = fileSrcExtract.exec(data_to_send)) !== null) { + window.jsbridge.sendFile(file_src[1]) + } + } + + var message = messageBarInput.value + if (message.length > 0) { + messageBarInput.value = "" + if (use_qt) { + window.jsbridge.sendMessage(message) + } else { + window.prompt("SEND:" + message) + } + } + grow_text_area() + reduce_send_container() +} + +/* exported acceptInvitation */ +function acceptInvitation() { + if (use_qt) { + window.jsbridge.acceptInvitation() + } else { + window.prompt("ACCEPT") + } +} +/* exported refuseInvitation */ +function refuseInvitation() { + if (use_qt) { + window.jsbridge.refuseInvitation() + } else { + window.prompt("REFUSE") + } +} +/* exported blockConversation */ +function blockConversation() { + if (use_qt) { + window.jsbridge.blockConversation() + } else { + window.prompt("BLOCK") + } +} + +/* exported sendFile */ +function selectFileToSend() { + if (use_qt) { + window.jsbridge.selectFile() + } else { + window.prompt("SEND_FILE") + } +} + +/* exported sendFile */ +function videoRecord() { + var rect = videoRecordButton.getBoundingClientRect() + if (use_qt) { + window.jsbridge.openVideoRecorder(rect.left + rect.width / 2, rect.top) + } else { + window.prompt(`VIDEO_RECORD:${rect.left + rect.width / 2}x${rect.top}`) + } +} + +function audioRecord() { + var rect = audioRecordButton.getBoundingClientRect() + if (use_qt) { + window.jsbridge.openAudioRecorder(rect.left + rect.width / 2, rect.top) + } else { + window.prompt(`AUDIO_RECORD:${rect.left + rect.width / 2}x${rect.top}`) + } +} + +/** + * Clear all messages. + */ +/* exported clearMessages */ +function clearMessages() { + historyBufferIndex = 0 + canLazyLoad = false + while (messages.firstChild) { + messages.removeChild(messages.firstChild) + } + + if (use_qt) { + backToBottomBtn.style.visibility="hidden" + window.jsbridge.emitMessagesCleared() + } else { + window.prompt("MESSAGE_CLEARED") + } +} + +/** + * Convert text to HTML. + */ +function escapeHtml(html) { + var text = document.createTextNode(html) + var div = document.createElement("div") + div.appendChild(text) + return div.innerHTML +} + +/** + * Get the youtube video id from a URL. + * @param url + */ +function youtube_id(url) { + const regExp = /^.*(youtu\.be\/|v\/|\/u\/w|embed\/|watch\?v=|&v=)([^#&?]*).*/ + const match = url.match(regExp) + return (match && match[2].length == 11) ? match[2] : null +} + +/** + * Emojis in a <pre> without <b> can disappears in a gtk webkit container + * So for now, use this workaround. + */ +function replace_emojis(text) { + let emojis_regex = /(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff])[\ufe0e\ufe0f]?(?:[\u0300-\u036f\ufe20-\ufe23\u20d0-\u20f0]|\ud83c[\udffb-\udfff])?(?:\u200d(?:[^\ud800-\udfff]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff])[\ufe0e\ufe0f]?(?:[\u0300-\u036f\ufe20-\ufe23\u20d0-\u20f0]|\ud83c[\udffb-\udfff])?)*/g + + text = text.replace(emojis_regex, (emoji) => "</pre><b>" + emoji + "</b><pre>") + return text +} + +/** + * Returns HTML message from the message text, cleaned and linkified. + * @param message_text + */ +function getMessageHtml(message_text) { + const escaped_message = escapeHtml(message_text) + + var linkified_message = linkifyHtml(escaped_message, linkifyOptions) // eslint-disable-line no-undef + const textPart = document.createElement("pre") + if (use_qt) { + textPart.innerHTML = linkified_message + } else { + textPart.innerHTML = replace_emojis(linkified_message) + } + var hyperlinks = textPart.getElementsByTagName("a") + for (var i = 0; i < hyperlinks.length; i++){ + hyperlinks[i].classList.add("text_link") + } + + return textPart.outerHTML +} + +/** + * Returns the message status, formatted for display + * @param message_delivery_status + */ +/* exported getMessageDeliveryStatusText */ +function getMessageDeliveryStatusText(message_delivery_status) { + return use_qt ? i18nStringData[message_delivery_status] : i18n.gettext(message_delivery_status) +} + +/** + * Returns the message date, formatted for display + */ +function getMessageTimestampText(message_timestamp, custom_format) { + const date = new Date(1000 * message_timestamp) + if (custom_format) { + return formatDate(date) + } else { + return date.toLocaleString() + } +} + +/** + * Update timestamps. + * @param message_div + */ +function updateTimestamps(messages_div) { + const timestamps = messages_div.getElementsByClassName("timestamp") + for (var c = timestamps.length - 1; c >= 0; --c) { + var timestamp = timestamps.item(c) + timestamp.innerHTML = getMessageTimestampText(timestamp.getAttribute("message_timestamp"), true) + } +} + +/** + * Convert a value in filesize + */ +function humanFileSize(bytes) { + var thresh = 1024 + if (Math.abs(bytes) < thresh) { + return bytes + " B" + } + var units = ["kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"] + var u = -1 + do { + bytes /= thresh + ++u + } while (Math.abs(bytes) >= thresh && u < units.length - 1) + return bytes.toFixed(1) + " " + units[u] +} + +/** + * Change the value of the progress bar. + * + * @param progress_bar + * @param message_object + */ +function updateProgressBar(progress_bar, message_object) { + var delivery_status = message_object["delivery_status"] + if (delivery_status === "ongoing" && "progress" in message_object && message_object["progress"] !== 100) { + var progress_percent = (100 * message_object["progress"] / message_object["totalSize"]) + if (progress_percent !== 100) + progress_bar.childNodes[0].setAttribute("style", "display: block; width: " + progress_percent + "%") + else + progress_bar.setAttribute("style", "display: none;") + } else + progress_bar.setAttribute("style", "display: none;") +} + +/** + * Check if a status is an error status + * @param + */ +function isErrorStatus(status) { + return (status === "failure" + || status === "awaiting peer timeout" + || status === "canceled" + || status === "unjoinable peer") +} + +/** + * Build a new file interaction + * @param message_id + */ +function fileInteraction(message_id) { + var message_wrapper = document.createElement("div") + message_wrapper.setAttribute("class", "message_wrapper") + + var transfer_info_wrapper = document.createElement("div") + transfer_info_wrapper.setAttribute("class", "transfer_info_wrapper") + message_wrapper.appendChild(transfer_info_wrapper) + + /* Buttons at the left for status information or accept/refuse actions. + The text is bold and clickable. */ + var left_buttons = document.createElement("div") + left_buttons.setAttribute("class", "left_buttons") + transfer_info_wrapper.appendChild(left_buttons) + + var full_div = document.createElement("div") + full_div.setAttribute("class", "full") + full_div.style.visibility = "hidden" + full_div.style.display = "none" + + var filename_wrapper = document.createElement("div") + filename_wrapper.setAttribute("class", "truncate-ellipsis") + + var message_text = document.createElement("span") + message_text.setAttribute("class", "filename") + filename_wrapper.appendChild(message_text) + + // And information like size or error message. + var informations_div = document.createElement("div") + informations_div.setAttribute("class", "informations") + + var text_div = document.createElement("div") + text_div.setAttribute("class", "text") + text_div.addEventListener("click", function () { + // ask ring to open the file + const filename = document.querySelector("#message_" + message_id + " .full").innerText + if (use_qt) { + window.jsbridge.openFile(filename) + } else { + window.prompt(`OPEN_FILE:${filename}`) + } + }) + + text_div.appendChild(filename_wrapper) + text_div.appendChild(full_div) + text_div.appendChild(informations_div) + transfer_info_wrapper.appendChild(text_div) + + // And finally, a progress bar + var message_transfer_progress_bar = document.createElement("span") + message_transfer_progress_bar.setAttribute("class", "message_progress_bar") + + var message_transfer_progress_completion = document.createElement("span") + message_transfer_progress_bar.appendChild(message_transfer_progress_completion) + message_wrapper.appendChild(message_transfer_progress_bar) + message_transfer_progress_completion.setAttribute("style", "display: none;") + + const internal_mes_wrapper = document.createElement("div") + internal_mes_wrapper.setAttribute("class", "internal_mes_wrapper") + internal_mes_wrapper.appendChild(message_wrapper) + + return internal_mes_wrapper +} + +function buildMsgTable(message_direction) { + var tbl = document.createElement("table") + + var row0 = document.createElement("tr") + var sender_image_cell = document.createElement("td") + sender_image_cell.setAttribute("class", "sender_image_cell") + var msg_cell = document.createElement("td") + msg_cell.setAttribute("class", "msg_cell") + + row0.appendChild((message_direction === "in") ? sender_image_cell : msg_cell) + row0.appendChild((message_direction === "in") ? msg_cell : sender_image_cell) + + tbl.appendChild(row0) + + var row1 = document.createElement("tr") + var dummy_cell = document.createElement("td") + dummy_cell.setAttribute("class", "dummy_cell") + var timestamp_cell = document.createElement("td") + timestamp_cell.setAttribute("class", "timestamp_cell") + + row1.appendChild((message_direction === "in") ? dummy_cell : timestamp_cell) + row1.appendChild((message_direction === "in") ? timestamp_cell : dummy_cell) + + tbl.appendChild(row1) + + return tbl +} + +/** + * Build information text for passed file interaction message object + * + * @param message_object message object containing file interaction info + */ +function buildFileInformationText(message_object) { + var informations_txt = getMessageTimestampText(message_object["timestamp"], true) + if (message_object["totalSize"] && message_object["progress"]) { + if (message_object["delivery_status"] === "finished") { + informations_txt += " - " + humanFileSize(message_object["totalSize"]) + } else { + informations_txt += " - " + humanFileSize(message_object["progress"]) + + " / " + humanFileSize(message_object["totalSize"]) + } + } + + return informations_txt + " - " + getMessageDeliveryStatusText(message_object["delivery_status"]) +} + +/** + * Update a file interaction (icons + filename + status + progress bar) + * + * @param message_div the message to update + * @param message_object new informations + * @param forceTypeToFile + */ +function updateFileInteraction(message_div, message_object, forceTypeToFile = false) { + if (!message_div.querySelector(".informations")) return // media + + if (!message_object["text"]) { + message_div.style.visibility = "collapse" + } else { + message_div.style.visibility = "visible" + } + + var acceptSvg = "<svg height=\"24\" viewBox=\"0 0 24 24\" width=\"24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M0 0h24v24H0z\" fill=\"none\"/><path d=\"M9 16.2L4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2z\"/></svg>", + refuseSvg = "<svg height=\"24\" viewBox=\"0 0 24 24\" width=\"24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z\"/><path d=\"M0 0h24v24H0z\" fill=\"none\"/></svg>", + fileSvg = "<svg class=\"filesvg\" height=\"24\" viewBox=\"0 0 24 24\" width=\"24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M16.5 6v11.5c0 2.21-1.79 4-4 4s-4-1.79-4-4V5c0-1.38 1.12-2.5 2.5-2.5s2.5 1.12 2.5 2.5v10.5c0 .55-.45 1-1 1s-1-.45-1-1V6H10v9.5c0 1.38 1.12 2.5 2.5 2.5s2.5-1.12 2.5-2.5V5c0-2.21-1.79-4-4-4S7 2.79 7 5v12.5c0 3.04 2.46 5.5 5.5 5.5s5.5-2.46 5.5-5.5V6h-1.5z\"/><path d=\"M0 0h24v24H0z\" fill=\"none\"/></svg>", + warningSvg = "<svg class=\"filesvg\" height=\"24\" viewBox=\"0 0 24 24\" width=\"24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M0 0h24v24H0z\" fill=\"none\"/><path d=\"M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z\"/></svg>" + if (is_swarm) { + acceptSvg = "<svg xmlns=\"http://www.w3.org/2000/svg\" height=\"24px\" viewBox=\"0 0 24 24\" width=\"24px\"><path d=\"M0 0h24v24H0z\" fill=\"none\"/><path d=\"M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z\"/></svg>" + } + var message_delivery_status = message_object["delivery_status"] + var message_direction = message_object["direction"] + var message_id = message_object["id"] + var message_text = message_object["text"] + + if (isImage(message_text) && message_delivery_status === "finished" && displayLinksEnabled && !forceTypeToFile) { + // Replace the old wrapper by the downloaded image + var old_wrapper = message_div.querySelector(".internal_mes_wrapper") + if (old_wrapper) { + old_wrapper.parentNode.removeChild(old_wrapper) + } + + var errorHandler = function () { + var wrapper = message_div.querySelector(".internal_mes_wrapper") + var message_wrapper = message_div.querySelector(".message_wrapper") + if (message_wrapper) { + message_wrapper.parentNode.removeChild(message_wrapper) + } + + var media_wrapper = message_div.querySelector(".media_wrapper") + if (media_wrapper) { + media_wrapper.parentNode.removeChild(media_wrapper) + } + + var new_interaction = fileInteraction(message_id) + var new_message_wrapper = new_interaction.querySelector(".message_wrapper") + wrapper.prepend(new_message_wrapper) + updateFileInteraction(message_div, message_object, true) + } + + var new_wrapper = mediaInteraction(message_id, message_direction, message_text, null, errorHandler) + message_div.insertBefore(new_wrapper, message_div.querySelector(".menu_interaction")) + message_div.querySelector("img").id = message_id + message_div.querySelector("img").msg_obj = message_object + return + } + + if (isAudio(message_text) && message_delivery_status === "finished" && displayLinksEnabled && !forceTypeToFile) { + // Replace the old wrapper by the downloaded audio + var old_wrapper = message_div.querySelector(".message_wrapper") + if (old_wrapper) { + old_wrapper.parentNode.removeChild(old_wrapper) + } + + var errorHandler = function () { + var wrapper = message_div.querySelector(".internal_mes_wrapper") + var wrapper_audio_video = message_div.querySelector(".message_type_audio_video_transfer") + wrapper_audio_video.parentNode.classList.remove("no-audio-overlay") + wrapper_audio_video.parentNode.removeChild(wrapper_audio_video) + + var message_wrapper = message_div.querySelector(".message_wrapper") + if (message_wrapper) { + message_wrapper.parentNode.removeChild(message_wrapper) + } + + var media_wrapper = message_div.querySelector(".audio") + if (media_wrapper) { + media_wrapper.parentNode.removeChild(media_wrapper) + } + + var new_interaction = fileInteraction(message_id) + var new_message_wrapper = new_interaction.querySelector(".message_wrapper") + wrapper.prepend(new_message_wrapper) + updateFileInteraction(message_div, message_object, true) + } + + const new_wrapper = document.createElement("audio") + new_wrapper.onerror = errorHandler + new_wrapper.setAttribute("src", "file://" + message_text) + new_wrapper.setAttribute("controls", "controls") + var audio_type = "audio/ogg" + if (message_text.toLowerCase().match(/\.(ogg)$/)) { + audio_type = "audio/ogg" + } else if (message_text.toLowerCase().match(/\.(flac)$/)) { + audio_type = "audio/flac" + } else if (message_text.toLowerCase().match(/\.(wav)$/)) { + audio_type = "audio/wav" + } else if (message_text.toLowerCase().match(/\.(mpeg)$/)) { + audio_type = "audio/mpeg" + } + new_wrapper.setAttribute("type", audio_type) + new_wrapper.setAttribute("class", "audio") + const audio_video_wrapper = document.createElement("div") + audio_video_wrapper.setAttribute("class", "message_type_audio_video_transfer") + audio_video_wrapper.appendChild(new_wrapper) + message_div.querySelector(".internal_mes_wrapper").insertBefore(audio_video_wrapper, message_div.querySelector(".timestamp")) + audio_video_wrapper.parentNode.classList.add("no-audio-overlay") + return + } + + if (isVideo(message_text) && message_delivery_status === "finished" && displayLinksEnabled && !forceTypeToFile) { + // Replace the old wrapper by the downloaded audio + var old_wrapper = message_div.querySelector(".message_wrapper") + if (old_wrapper) { + old_wrapper.parentNode.removeChild(old_wrapper) + } + + var errorHandler = function () { + var wrapper = message_div.querySelector(".internal_mes_wrapper") + var wrapper_audio_video = message_div.querySelector(".message_type_audio_video_transfer") + wrapper_audio_video.parentNode.classList.remove("no-audio-overlay") + wrapper_audio_video.parentNode.removeChild(wrapper_audio_video) + + var message_wrapper = message_div.querySelector(".message_wrapper") + if (message_wrapper) { + message_wrapper.parentNode.removeChild(message_wrapper) + } + + var media_wrapper = message_div.querySelector(".video") + if (media_wrapper) { + media_wrapper.parentNode.removeChild(media_wrapper) + } + + var new_interaction = fileInteraction(message_id) + var new_message_wrapper = new_interaction.querySelector(".message_wrapper") + wrapper.prepend(new_message_wrapper) + updateFileInteraction(message_div, message_object, true) + } + + var hideContext = function () {return false} + const new_wrapper = document.createElement("video") + new_wrapper.onerror = errorHandler + new_wrapper.oncontextmenu = hideContext + new_wrapper.setAttribute("src", "file://" + message_text) + new_wrapper.setAttribute("controls", "controls") + var audio_type = "video/mp4" + if (message_text.toLowerCase().match(/\.(mp4)$/)) { + audio_type = "video/mp4" + } else if (message_text.toLowerCase().match(/\.(avi)$/)) { + audio_type = "video/avi" + } else if (message_text.toLowerCase().match(/\.(mov)$/)) { + audio_type = "video/mov" + } else if (message_text.toLowerCase().match(/\.(webm)$/)) { + audio_type = "video/webm" + } else if (message_text.toLowerCase().match(/\.(rmvb)$/)) { + audio_type = "video/rmvb" + } + new_wrapper.setAttribute("type", audio_type) + new_wrapper.setAttribute("class", "video") + const audio_video_wrapper = document.createElement("div") + + audio_video_wrapper.setAttribute("class", "message_type_audio_video_transfer") + audio_video_wrapper.appendChild(new_wrapper) + message_div.querySelector(".internal_mes_wrapper").insertBefore(audio_video_wrapper, message_div.querySelector(".timestamp")) + audio_video_wrapper.parentNode.classList.add("no-video-overlay") + return + } + + // Set informations text + var informations_div = message_div.querySelector(".informations") + informations_div.innerText = buildFileInformationText(message_object) + + // Update flat buttons + var left_buttons = message_div.querySelector(".left_buttons") + left_buttons.innerHTML = "" + + if (message_delivery_status === "awaiting host" || + message_delivery_status.indexOf("ongoing") === 0) { + + if (message_delivery_status.indexOf("ongoing") !== 0) { + // add buttons to accept or refuse a call. + var accept_button = document.createElement("div") + accept_button.innerHTML = acceptSvg + accept_button.setAttribute("title", use_qt ? i18nStringData["Accept"] : + i18n.gettext("Accept")) + accept_button.setAttribute("class", "flat-button accept") + accept_button.onclick = function () { + if (use_qt) { + window.jsbridge.acceptFile(message_id) + } else { + window.prompt(`ACCEPT_FILE:${message_id}`) + } + } + left_buttons.appendChild(accept_button) + } + + if (!is_swarm || message_delivery_status.indexOf("ongoing") === 0) { + var refuse_button = document.createElement("div") + refuse_button.innerHTML = refuseSvg + refuse_button.setAttribute("title", use_qt ? i18nStringData["Refuse"] : + i18n.gettext("Refuse")) + refuse_button.setAttribute("class", "flat-button refuse") + refuse_button.onclick = function () { + if (use_qt) { + window.jsbridge.refuseFile(message_id) + } else { + window.prompt(`REFUSE_FILE:${message_id}`) + } + } + left_buttons.appendChild(refuse_button) + } + + } else if (message_delivery_status !== "awaiting peer") { + var status_button = document.createElement("div") + var statusFile = fileSvg + if (isErrorStatus(message_delivery_status)) + statusFile = warningSvg + status_button.innerHTML = statusFile + status_button.setAttribute("class", "flat-button") + left_buttons.appendChild(status_button) + } + + message_div.querySelector(".full").innerText = message_text + var displayName = message_object["displayName"] + if (!displayName || displayName === "") { + displayName = message_text.split("/").pop() // If non swarm displayName will be not set, we can take the path + } + message_div.querySelector(".filename").innerText = displayName + updateProgressBar(message_div.querySelector(".message_progress_bar"), message_object) + + if (!message_div.querySelector(`.dropdown_${message_id}`)) { + if (!is_swarm || message_delivery_status === "finished") { + var message_dropdown = buildMessageDropdown(message_id, message_object["displayName"]) + message_div.appendChild(message_dropdown) + } + } +} + +/** + * Return if a file is an image + * @param file + */ +function isImage(file) { + return file.toLowerCase().match(/\.(jpeg|jpg|gif|png)$/) !== null +} + +/** + * Return if a file is an audio + * @param file + */ +function isAudio(file) { + return file.toLowerCase().match(/\.(mp3|mpeg|ogg|flac|wav)$/) !== null +} + +/** + * Return if a file is an video + * @param file + */ +function isVideo(file) { + return file.toLowerCase().match(/\.(mp4|avi|webm|mov|rmvb)$/) !== null +} + +/** + * Return if a file is a youtube video + * @param file + */ +function isYoutubeVideo(file) { + const availableProtocols = ["http:", "https:"] + const videoHostname = ["youtube.com", "www.youtube.com", "youtu.be"] + const urlParser = document.createElement("a") + urlParser.href = file + return (availableProtocols.includes(urlParser.protocol) && videoHostname.includes(urlParser.hostname)) +} + +/** + * Build a container for passed video thumbnail + * @param linkElt video thumbnail div + */ +function buildVideoContainer(linkElt) { + const containerElt = document.createElement("div") + containerElt.setAttribute("class", "containerVideo") + const playDiv = document.createElement("div") + playDiv.setAttribute("class", "playVideo") + playDiv.innerHTML = "<svg fill=\"#ffffff\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\">\ + <path d=\"M8 5v14l11-7z\"/>\ + <path d=\"M0 0h24v24H0z\" fill=\"none\"/>\ + </svg>" + linkElt.appendChild(playDiv) + containerElt.appendChild(linkElt) + + return containerElt +} + +/** + * Try to show an image + * @param message_id + * @param link to show + * @param errorHandler the new media's onerror field will be set to this function + */ +function mediaInteraction(message_id, message_direction, link, errorHandler) { + /* TODO promise? + Try to display images. */ + const media_wrapper = document.createElement("div") + media_wrapper.setAttribute("class", "media_wrapper") + const linkElt = document.createElement("a") + linkElt.href = link + linkElt.style.textDecoration = "none" + linkElt.style.border = "none" + const imageElt = document.createElement("img") + + imageElt.src = link + + /* Note, here, we don't check the size of the image. + in the future, we can check the content-type and content-length with a request + and maybe disable svg */ + + if (isInitialLoading) { + /* During initial load, make sure the scrollbar stays at the bottom. + Also, the final scrollHeight is only known after the last image was + loaded. We want to display a specific number of messages screens so + we have to set up a callback (on_image_load_finished) which will + check on that and reschedule a new display batch if not enough + messages have been loaded in the DOM. */ + imagesLoadingCounter++ + imageElt.onload = function () { + back_to_bottom() + on_image_load_finished() + } + + if (errorHandler) { + imageElt.onerror = function () { + errorHandler() + back_to_bottom() + on_image_load_finished() + } + } + } else if (messages.scrollTop >= messages.scrollHeight - messages.clientHeight - scrollDetectionThresh) { + /* Keep the scrollbar at the bottom. Images are loaded asynchronously and + the scrollbar position is changed each time an image is loaded and displayed. + In order to make sure the scrollbar stays at the bottom, reset scrollbar + position each time an image was loaded. */ + imageElt.onload = back_to_bottom + + if (errorHandler) { + imageElt.onerror = function () { + errorHandler() + back_to_bottom() + } + } + } else if (errorHandler) { + imageElt.onerror = errorHandler + } + + linkElt.appendChild(imageElt) + media_wrapper.appendChild(linkElt) + const internal_mes_wrapper = document.createElement("div") + internal_mes_wrapper.setAttribute("class", "internal_mes_wrapper") + internal_mes_wrapper.appendChild(media_wrapper) + + return internal_mes_wrapper +} + +/** + * @param container_link the anchor tag that is the parent of the text container + * @param title title of the website page + * @param description description of the website + * @param url url that is sent in the message + */ +function buildPreviewTextContainer(container_link, title, description, url){ + var text_container = document.createElement("div") + text_container.setAttribute("class", "preview_text_container") + container_link.appendChild(text_container) + + var card_title = document.createElement("pre") + card_title.setAttribute("class", "preview_card_title") + title !== null ? card_title.appendChild(document.createTextNode(title)) : card_title.appendChild(document.createTextNode("")) + text_container.appendChild(card_title) + if (description !== null && description !== "" && description !== undefined){ + var card_subtitle = document.createElement("p") + card_subtitle.setAttribute("class", "preview_card_subtitle") + card_subtitle.appendChild(document.createTextNode(description)) + text_container.appendChild(card_subtitle) + } + // reduce url to just its domain for aesthetic purposes + var domain = (new URL(url)) + domain = (domain.hostname).replace("www.", "") + var card_link = document.createElement("p") + card_link.setAttribute("class", "preview_card_link") + card_link.appendChild(document.createTextNode(domain)) + text_container.appendChild(card_link) +} + +/** + * @param internal_message_wrapper the message wrapper of the message being manipulated + * @param title title retrieved from url + * @param img image retrieved form url + * @param description description of website + * @param url url that was sent + * @param message_direction whether the message is being received or sent + */ +function buildPreviewHtml(internal_message_wrapper, title, img, description, url, message_direction) { + // Create a wrapper for the preview + var external_preview_wrapper = document.createElement("div") + external_preview_wrapper.setAttribute("class", "msg_cell_with_preview") + // Create the cell that will wrap the preview + var preview_wrapper = document.createElement("div") + external_preview_wrapper.appendChild(preview_wrapper) + var timestamp = internal_message_wrapper.getElementsByClassName("timestamp")[0] + // check if theres a timesstamp and append accordingly + timestamp ? internal_message_wrapper.insertBefore(external_preview_wrapper, timestamp) : internal_message_wrapper.appendChild(external_preview_wrapper) + preview_wrapper.setAttribute("class", message_direction === "in" ? "preview_wrapper_in" : "preview_wrapper_out") + var container = document.createElement("div") + container.setAttribute("class", "preview_card_container") + preview_wrapper.appendChild(container) + var card_container = document.createElement("div") + message_direction === "in" ? card_container.setAttribute("class", "card_container_in") : card_container.setAttribute("class", "card_container_out") + container.appendChild(card_container) + var container_link = document.createElement("a") + container_link.setAttribute("class", "preview_container_link") + // add http to ensure that users will be taken + // to the webpage when the element is clicked + // and set url of anchor tag + if (url !== null){ + if (!url.includes("http://") && !url.includes("https://")){ + url = "http://".concat(url) + } + container_link.setAttribute("href", url) + container_link.setAttribute("target", "_self") + } + card_container.appendChild(container_link) + // create image and set image found as property if one exists + var card_image = document.createElement("img") + card_image.setAttribute("class", "preview_image") + if (img !== null && img !== undefined){ + card_image.setAttribute("src", img) + card_image.onerror = function(){ + card_image.remove() + var msg_wrap = internal_message_wrapper.getElementsByClassName("message_wrapper_with_image_preview") + if (msg_wrap.length > 0){ + msg_wrap[0].classList.add("message_wrapper_without_image_preview") + msg_wrap[0].classList.remove("message_wrapper_with_image_preview") + } + } + } + else if (img === null){ + var msg_wrap = internal_message_wrapper.getElementsByClassName("message_wrapper_with_image_preview")[0] + msg_wrap.classList.remove("message_wrapper_with_image_preview") + msg_wrap.classList.add("message_wrapper_without_image_preview") + } + // if there is an image associated with the hyperlink + // then the message's css must be adjusted accordingly + container_link.appendChild(card_image) + // create container that will hold the title, description and domain + buildPreviewTextContainer(container_link, title, description, url) +} + + +/** + * Retrieves information needed for hyperlink preview and creates html element accordingly + * @param message_id id of the message that contains specificied url + * @param message_text text containing hyperlink + * @param message_direction string determining whether the message had been sent or received + */ +function createHyperlinkPreview(message_id, message_text, message_direction) { + var title = null + var description = null + var img = null + var link_array = linkify.find(message_text) + var url = link_array[0].href + //scrolling + var atEnd = messages.scrollTop >= messages.scrollHeight - messages.clientHeight - scrollDetectionThresh + + fetch(url).then(function (response) { + return response.text() + }).then(function (html) { + // create DOM from html string + var parser = new DOMParser() + var doc = parser.parseFromString(html, "text/html") + if (!url.includes("twitter.com")){ + title = getTitle(doc) + img = getImage(doc, url) + description = getDescription(doc) + } else{ + title = "Twitter. It's what's happening." + } + // Retrieve message that will be manipulated + var message_string = "message_" + var message_id_string = message_string.concat(message_id) + var main_text = document.getElementById(message_id_string) + // ensure that message exists + if (main_text === null ){ + return + } + // Get message wrapper + var internal_message_wrapper = main_text.getElementsByClassName("internal_mes_wrapper")[0] + internal_message_wrapper.getElementsByClassName("message_wrapper")[0].classList.add("message_wrapper_with_image_preview") + internal_message_wrapper.getElementsByClassName("message_text")[0].classList.add("message_text_with_preview") + + buildPreviewHtml(internal_message_wrapper, title, img, description, url, message_direction) + // fix scrolling + if (atEnd) { + messages.scrollTop = messages.scrollHeight + } + }).catch(function (err) { + // Error occured while fetching document + console.warn("Warning", err) + }) +} + +/** + * Build a new hyperlink interaction + * @param message_id id of the message + * @param message_direction string determining whether the message had been sent or received + * @param the text itself of the message + * @param htmlText the DOM to show + */ +function hyperlinkInteraction(message_id, message_direction, message_text, htmlText) { + var main_text = textInteraction(message_id, message_direction, htmlText) + createHyperlinkPreview (message_id, message_text, message_direction) + return main_text +} + +/** + * Build a new text interaction + * @param message_id + * @param htmlText the DOM to show + */ +function textInteraction(message_id, message_direction, htmlText) { + const message_wrapper = document.createElement("div") + message_wrapper.setAttribute("class", "message_wrapper") + var message_text = document.createElement("div") + message_text.setAttribute("class", "message_text") + message_text.setAttribute("dir", "auto") + message_text.innerHTML = htmlText + message_wrapper.appendChild(message_text) + // TODO STATUS + + const internal_mes_wrapper = document.createElement("div") + internal_mes_wrapper.setAttribute("class", "internal_mes_wrapper") + internal_mes_wrapper.appendChild(message_wrapper) + + + return internal_mes_wrapper +} + +/** + * Build message dropdown + * @return a message dropdown for passed message id + */ +function buildMessageDropdown(message_id, display_name) { + const menu_element = document.createElement("div") + menu_element.setAttribute("class", "menu_interaction") + menu_element.innerHTML = + `<input type="checkbox" id="showmenu${message_id}" class="showmenu"> + <label for="showmenu${message_id}"> + <svg fill="#888888" height="12" viewBox="0 0 24 24" width="12" xmlns="http://www.w3.org/2000/svg"> + <path d="M0 0h24v24H0z" fill="none"/> + <path d="M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/> + </svg> + </label>` + menu_element.onclick = function () { + const button = this.querySelector(".showmenu") + button.checked = !button.checked + } + menu_element.onmouseleave = function () { + const button = this.querySelector(".showmenu") + button.checked = false + } + const dropdown = document.createElement("div") + const dropdown_classes = [ + "dropdown", + `dropdown_${message_id}` + ] + dropdown.setAttribute("class", dropdown_classes.join(" ")) + + const save = document.createElement("div") + save.setAttribute("class", "menuoption") + if (is_swarm) { + if (use_qt) { + save.innerHTML = "Copy to downloads" + } else { + save.innerHTML = i18n.gettext("Copy to downloads") + } + save.msg_id = message_id + save.display_name = display_name + save.onclick = function () { + if (use_qt) { + window.jsbridge.copyToDownloads(this.msg_id, this.display_name) + } else { + window.prompt(`COPY:${this.msg_id}:${this.display_name}`) + } + } + dropdown.appendChild(save) + } else { + const remove = document.createElement("div") + remove.setAttribute("class", "menuoption") + if (use_qt) { + remove.innerHTML = "Delete" + } else { + remove.innerHTML = i18n.gettext("Delete") + } + remove.msg_id = message_id + remove.onclick = function () { + if (use_qt) { + window.jsbridge.deleteInteraction(`${this.msg_id}`) + } else { + window.prompt(`DELETE_INTERACTION:${this.msg_id}`) + } + } + dropdown.appendChild(remove) + } + menu_element.appendChild(dropdown) + + return menu_element +} + +/** + * Update a text interaction (text) + * @param message_div the message to update + * @param delivery_status the status of the message + */ +function updateTextInteraction(message_div, delivery_status) { + if (!message_div.querySelector(".message_text")) return // media + const message_text = message_div.querySelector(".message_text") + const message_in = message_div.querySelector(".message_in") + switch(delivery_status) + { + case "ongoing": + case "sending": + message_text.style.color = "#888" + break + case "failure": + var failure_div = message_div.querySelector(".failure") + if (!failure_div) { + failure_div = document.createElement("div") + failure_div.setAttribute("class", "failure") + failure_div.innerHTML = "<svg overflow=\"visible\" viewBox=\"0 -2 16 14\" height=\"16px\" width=\"16px\"><path class=\"status-x x-first\" stroke=\"#AA0000\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"3\" fill=\"none\" d=\"M4,4 L12,12\"/><path class=\"status-x x-second\" stroke=\"#AA0000\" stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"3\" fill=\"none\" d=\"M12,4 L4,12\"/></svg>" + // add failure animation to message + message_div.insertBefore(failure_div, message_div.querySelector(".menu_interaction")) + } + if (message_in) + message_text.style.color = "var(--message-in-txt)" + else + message_text.style.color = "var(--message-out-txt)" + break + case "sent": + case "finished": + case "unknown": + case "read": + if (message_in) + message_text.style.color = "var(--message-in-txt)" + else + message_text.style.color = "var(--message-out-txt)" + break + default: + break + } +} + +/** + * Build a new interaction (call or contact) + */ +function actionInteraction() { + var message_wrapper = document.createElement("div") + message_wrapper.setAttribute("class", "message_wrapper") + + // A file interaction contains buttons at the left of the interaction + // for the status or accept/refuse buttons + var left_buttons = document.createElement("div") + left_buttons.setAttribute("class", "left_buttons") + message_wrapper.appendChild(left_buttons) + + // Also contains a bold clickable text + var text_div = document.createElement("div") + text_div.setAttribute("class", "text") + message_wrapper.appendChild(text_div) + return message_wrapper +} + +/** + * Update a call interaction (icon + text) + * @param message_div the message to update + * @param message_object new informations + */ +function updateCallInteraction(message_div, message_object) { + const outgoingCall = "<svg fill=\"#219d55\" height=\"24\" viewBox=\"0 0 24 24\" width=\"24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M0 0h24v24H0z\" fill=\"none\"/><path d=\"M9 5v2h6.59L4 18.59 5.41 20 17 8.41V15h2V5z\"/></svg>" + const callMissed = "<svg fill=\"#dc2719\" height=\"24\" viewBox=\"0 0 24 24\" width=\"24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M0 0h24v24H0z\" fill=\"none\"/><path d=\"M19.59 7L12 14.59 6.41 9H11V7H3v8h2v-4.59l7 7 9-9z\"/></svg>" + const outgoingMissed = "<svg fill=\"#dc2719\" height=\"24\" viewBox=\"0 0 24 24\" width=\"24\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><defs><path d=\"M24 24H0V0h24v24z\" id=\"a\"/></defs><clipPath id=\"b\"><use overflow=\"visible\" xlink:href=\"#a\"/></clipPath><path clip-path=\"url(#b)\" d=\"M3 8.41l9 9 7-7V15h2V7h-8v2h4.59L12 14.59 4.41 7 3 8.41z\"/></svg>" + const callReceived = "<svg fill=\"#219d55\" height=\"24\" viewBox=\"0 0 24 24\" width=\"24\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M0 0h24v24H0z\" fill=\"none\"/><path d=\"M20 5.41L18.59 4 7 15.59V9H5v10h10v-2H8.41z\"/></svg>" + + const message_text = message_object["text"] + const message_direction = message_object["direction"] + const message_duration = message_object["duration"] + const message_sender = message_object["sender"] + + const missed = message_duration === 0 ? true : false + + message_div.querySelector(".text").innerText = message_text + + var left_buttons = message_div.querySelector(".left_buttons") + left_buttons.innerHTML = "" + var status_button = document.createElement("div") + var statusFile = "" + if (missed) + statusFile = (message_direction === "in") ? callMissed : outgoingMissed + else + statusFile = (message_direction === "in") ? callReceived : outgoingCall + status_button.innerHTML = statusFile + status_button.setAttribute("class", "flat-button") + left_buttons.appendChild(status_button) +} + +/** + * Update a contact interaction (icon + text) + * @param message_div the message to update + * @param message_object new informations + */ +function updateContactInteraction(message_div, message_object) { + const message_text = message_object["text"] + + message_div.querySelector(".text").innerText = message_text +} + +/** + * Remove an interaction from the conversation + * @param interaction_id + */ +/* exported removeInteraction */ +function removeInteraction(interaction_id) { + var interaction = document.getElementById(`message_${interaction_id}`) + if (!interaction) { + return + } + + if (interaction.previousSibling) { + /* if element was the most recently received message, make sure the + last_message property is given away to the previous sibling */ + if (interaction.classList.contains("last_message")) { + interaction.previousSibling.classList.add("last_message") + } + + /* same for timestamp */ + var timestamp = interaction.querySelector(".timestamp") + var previousTimeStamp = interaction.previousSibling.querySelector(".timestamp") + if (timestamp && !previousTimeStamp) { + interaction.previousSibling.querySelector(".internal_mes_wrapper").appendChild(timestamp) + } + } + + var firstMessage = getPreviousInteraction(interaction) + var secondMessage = getNextInteraction(interaction) + + updateSequencing(firstMessage, secondMessage) + + interaction.parentNode.removeChild(interaction) +} + +/** + * Build a message div for passed message object + * @param message_object to treat + */ +function buildNewMessage(message_object) { + const message_id = message_object["id"] + const message_type = message_object["type"] + const message_text = message_object["text"] + const message_direction = message_object["direction"] + const delivery_status = message_object["delivery_status"] + const message_sender_contact_method = message_object["sender_contact_method"] + + var classes = [ + "message", + `message_${message_direction}`, + `message_type_${message_type}` + ] + + var type = "" + var message_div = document.createElement("div") + message_div.setAttribute("id", `message_${message_id}`) + message_div.setAttribute("class", classes.join(" ")) + + const need_sender = (message_type === "data_transfer" || message_type === "text") + if (need_sender) { + var message_sender_image = document.createElement("span") + message_sender_image.setAttribute("class", `sender_image sender_image_${message_sender_contact_method}`) + message_div.appendChild(message_sender_image) + } + + // Build main content + if (message_type === "data_transfer") { + if (isImage(message_text) && delivery_status === "finished" && displayLinksEnabled) { + var errorHandler = function () { + var wrapper = message_div.querySelector(".internal_mes_wrapper") + var message_wrapper = message_div.querySelector(".message_wrapper") + if (message_wrapper) { + message_wrapper.parentNode.removeChild(message_wrapper) + } + + var media_wrapper = message_div.querySelector(".media_wrapper") + if (media_wrapper) { + media_wrapper.parentNode.removeChild(media_wrapper) + } + + var new_interaction = fileInteraction(message_id) + var new_message_wrapper = new_interaction.querySelector(".message_wrapper") + wrapper.prepend(new_message_wrapper) + updateFileInteraction(message_div, message_object, true) + } + message_div.append(mediaInteraction(message_id, message_direction, message_text, null, errorHandler)) + message_div.querySelector("img").id = message_id + message_div.querySelector("img").msg_obj = message_object + } else { + message_div.append(fileInteraction(message_id)) + updateProgressBar(message_div.querySelector(".message_progress_bar"), message_object) + } + if (!message_div.querySelector(`.dropdown_${message_id}`)) { + if (is_swarm && delivery_status === "finished") { + var message_dropdown = buildMessageDropdown(message_id, message_object["displayName"]) + message_div.appendChild(message_dropdown) + } + } + } else if (message_type === "text") { + // TODO add the possibility to update messages (remove and rebuild) + const htmlText = getMessageHtml(message_text) + if (displayLinksEnabled) { + const parser = new DOMParser() + const DOMMsg = parser.parseFromString(htmlText, "text/xml") + const links = DOMMsg.querySelectorAll("a") + if (DOMMsg.childNodes.length && links.length) { + var isTextToShow = (DOMMsg.childNodes[0].childNodes.length > 1) + if (!isTextToShow && (isImage(message_text))) { + type = "media" + message_div.append(mediaInteraction(message_id, message_direction, message_text)) + } + } + } + if (type !== "media" && linkify.find(message_text).length > 0 && displayLinksEnabled){ + message_div.append(hyperlinkInteraction(message_id, message_direction, message_text, htmlText)) + } + else if (type !== "media") { + type = "text" + message_div.append(textInteraction(message_id, message_direction, htmlText)) + } + } else if (message_type === "call" || message_type === "contact") { + message_div.append(actionInteraction()) + } else { + const temp = document.createElement("div") + temp.innerText = message_type + message_div.appendChild(temp) + } + + if (message_type !== "typing" && !is_swarm && !message_div.querySelector(`.dropdown_${message_id}`)) { + var message_dropdown = buildMessageDropdown(message_id) + message_div.appendChild(message_dropdown) + } + + return message_div +} + +function addSenderImage(message_div, message_type, message_sender_contact_method) { + const need_sender = (message_type === "data_transfer" || message_type === "text") + if (need_sender) { + var sender_image_cell = message_div.querySelector(".sender_image_cell") + if (sender_image_cell) { + var message_sender_image = document.createElement("span") + var cssSafeStr = message_sender_contact_method.replace(/@/g, "_").replace(/\./g, "_") + message_sender_image.setAttribute("class", `sender_image sender_image_${cssSafeStr}`) + sender_image_cell.appendChild(message_sender_image) + } else { + console.warn("can't find sender_image_cell") + } + } +} + +/** + * Build a timestamp for passed message object + * @param message_object to treat + */ +function buildNewTimestamp(message_object) { + const message_type = message_object["type"] + const message_direction = message_object["direction"] + const message_timestamp = message_object["timestamp"] + + const formattedTimestamp = getMessageTimestampText(message_timestamp, true) + const date_elt = document.createElement("div") + + date_elt.innerText = formattedTimestamp + var typeIsCallOrContact = (message_type === "call" || message_type === "contact") + var timestamp_div_classes = ["timestamp", typeIsCallOrContact ? "timestamp_action" : `timestamp_${message_direction}`] + date_elt.setAttribute("class", timestamp_div_classes.join(" ")) + date_elt.setAttribute("message_timestamp", message_timestamp) + + return date_elt +} + +/** + * Add a message to the conversation. + * @param message_object to treat + * @param new_message if it's a new message or if we need to update + * @param insert_after if we want the message at the end or the top of the conversation + * @param messages_div + */ +function addOrUpdateMessage(message_object, new_message, insert_after = true, messages_div) { + const message_id = message_object["id"] + const message_type = message_object["type"] + const message_direction = message_object["direction"] + const delivery_status = message_object["delivery_status"] + + var message_div = messages_div.querySelector("#message_" + message_id) + if (new_message) { + if (message_div) + return; + message_div = buildNewMessage(message_object) + + /* Show timestamp if either: + - message has type call or contact + - or most recently added timestamp in this set is different + - or message is the first message in this set */ + + var date_elt = buildNewTimestamp(message_object) + var timestamp = messages_div.querySelector(".timestamp") + + if (message_type === "call" || message_type === "contact") { + message_div.querySelector(".message_wrapper").appendChild(date_elt) + } else if (insert_after || !timestamp || timestamp.className !== date_elt.className + || timestamp.innerHTML !== date_elt.innerHTML) { + message_div.querySelector(".internal_mes_wrapper").appendChild(date_elt) + } + + var isGenerated = message_type === "call" || message_type === "contact" + if (isGenerated) { + message_div.classList.add("generated_message") + } + + if (insert_after) { + var previousMessage = messages_div.lastChild + messages_div.appendChild(message_div) + computeSequencing(previousMessage, message_div, null, insert_after) + if (previousMessage) { + if (previousMessage.id === "message_typing") { + previousMessage.parentNode.removeChild(previousMessage) + message_div.parentNode.appendChild(previousMessage) + } else { + previousMessage.classList.remove("last_message") + message_div.classList.add("last_message") + } + } + + /* When inserting at the bottom we should also check that the + previously sent message does not have the same timestamp. + If it's the case, remove it.*/ + if (message_div.previousSibling) { + var previous_timestamp = message_div.previousSibling.querySelector(".timestamp") + if (previous_timestamp && + previous_timestamp.className === date_elt.className && + previous_timestamp.innerHTML === date_elt.innerHTML && + !message_div.previousSibling.classList.contains("last_of_sequence")) { + previous_timestamp.parentNode.removeChild(previous_timestamp) + } + } + } else { + var nextMessage = messages_div.firstChild + messages_div.prepend(message_div) + computeSequencing(message_div, nextMessage, null, insert_after) + } + } + + if (!is_swarm && isErrorStatus(delivery_status) && message_direction === "out") { + const dropdown = messages_div.querySelector(`.dropdown_${message_id}`) + if (!dropdown.querySelector(".retry")) { + const retry = document.createElement("div") + retry.setAttribute("class", "retry") + if (use_qt) { + retry.innerHTML = "Retry" + } else { + retry.innerHTML = i18n.gettext("Retry") + } + retry.msg_id = message_id + retry.onclick = function () { + if (use_qt) { + window.jsbridge.retryInteraction(`${this.msg_id}`) + } else { + window.prompt(`RETRY_INTERACTION:${this.msg_id}`) + } + } + dropdown.insertBefore(retry, message_div.querySelector(".delete")) + } + } + + // Update informations if needed + if (message_type === "data_transfer") + updateFileInteraction(message_div, message_object) + if (message_type === "text" && message_direction === "out") + // Modify sent status if necessary + updateTextInteraction(message_div, delivery_status) + if (message_type === "call") + updateCallInteraction(message_div, message_object) + if (message_type === "contact") + updateContactInteraction(message_div, message_object) + + // Clean timestamps + updateTimestamps(messages_div) +} + +function getNextInteraction(interaction, includeLazyLoadedBlock = true) { + var nextInteraction = interaction.nextSibling + if (!nextInteraction && includeLazyLoadedBlock) { + var nextBlock = interaction.parentNode.nextElementSibling + if (nextBlock) { + nextInteraction = nextBlock.firstElementChild + } + } + return nextInteraction +} + +function getPreviousInteraction(interaction, includeLazyLoadedBlock = true) { + var previousInteraction = interaction.previousSibling + if (!previousInteraction && includeLazyLoadedBlock) { + var previousBlock = interaction.parentNode.previousElementSibling + if (previousBlock) { + previousInteraction = previousBlock.lastElementChild + } + } + return previousInteraction +} + +function isSequenceBreak(firstMessage, secondMessage, insert_after = true) { + if (!firstMessage || !secondMessage) { + return false + } + var first_message_direction = firstMessage.classList.contains("message_out") ? "out" : "in" + var second_message_direction = secondMessage.classList.contains("message_out") ? "out" : "in" + if (second_message_direction != first_message_direction) { + return true + } + var firstMessageIsGenerated = firstMessage.classList.contains("generated_message") + var secondMessageIsGenerated = secondMessage.classList.contains("generated_message") + if (firstMessageIsGenerated != secondMessageIsGenerated) { + return true + } + if (insert_after) { + const internal_message_wrapper = firstMessage.querySelector(".internal_mes_wrapper") + if (internal_message_wrapper) { + const firstTimestamp = internal_message_wrapper.querySelector(".timestamp") + return !!(firstTimestamp) && firstTimestamp.innerHTML !== "just now" + } + return false + } else { + const internal_message_wrapper = firstMessage.querySelector(".internal_mes_wrapper") + if (internal_message_wrapper) { + return !!(internal_message_wrapper.querySelector(".timestamp")) + } + return false + } +} + +function updateSequencing(firstMessage, secondMessage) { + if (firstMessage) { + if (secondMessage) { + var sequence_break = isSequenceBreak(firstMessage, secondMessage, false) + if (sequence_break) { + if (firstMessage.classList.contains("middle_of_sequence")) { + firstMessage.classList.remove("middle_of_sequence") + firstMessage.classList.add("last_of_sequence") + } else if (firstMessage.classList.contains("first_of_sequence")) { + firstMessage.classList.remove("first_of_sequence") + firstMessage.classList.add("single_message") + } + if (secondMessage.classList.contains("middle_of_sequence")) { + secondMessage.classList.remove("middle_of_sequence") + secondMessage.classList.add("first_of_sequence") + } else if (secondMessage.classList.contains("last_of_sequence")) { + secondMessage.classList.remove("last_of_sequence") + secondMessage.classList.add("single_message") + } + } else { + if (firstMessage.classList.contains("last_of_sequence")) { + firstMessage.classList.remove("last_of_sequence") + firstMessage.classList.add("middle_of_sequence") + } else if (firstMessage.classList.contains("single_message")) { + firstMessage.classList.remove("single_message") + firstMessage.classList.add("first_of_sequence") + } + if (secondMessage.classList.contains("first_of_sequence")) { + secondMessage.classList.remove("first_of_sequence") + secondMessage.classList.add("middle_of_sequence") + } else if (secondMessage.classList.contains("single_message")) { + secondMessage.classList.remove("single_message") + secondMessage.classList.add("last_of_sequence") + } + } + } else { + // this is the last interaction of the conversation + if (firstMessage.classList.contains("first_of_sequence")) { + firstMessage.classList.remove("first_of_sequence") + firstMessage.classList.add("single_message") + } else if (firstMessage.classList.contains("middle_of_sequence")) { + firstMessage.classList.remove("middle_of_sequence") + firstMessage.classList.add("last_of_sequence") + } + } + } else if (secondMessage) { + // this is the first interaction of the conversation + if (secondMessage.classList.contains("middle_of_sequence")) { + secondMessage.classList.remove("middle_of_sequence") + secondMessage.classList.add("first_of_sequence") + } else if (secondMessage.classList.contains("last_of_sequence")) { + secondMessage.classList.remove("last_of_sequence") + secondMessage.classList.add("single_message") + } + } +} + +function computeSequencing(firstMessage, secondMessage, lazyLoadingBlock, insert_after = true) { + if (insert_after) { + if (secondMessage) { + var secondMessageIsGenerated = secondMessage.classList.contains("generated_message") + if (firstMessage && !secondMessageIsGenerated) { + var firstMessageIsGenerated = firstMessage.classList.contains("generated_message") + var sequence_break = isSequenceBreak(firstMessage, secondMessage) + if (sequence_break) { + secondMessage.classList.add("single_message") + } else { + if (firstMessage.classList.contains("single_message")) { + firstMessage.classList.remove("single_message") + firstMessage.classList.add("first_of_sequence") + } else if (firstMessage.classList.contains("last_of_sequence")) { + firstMessage.classList.remove("last_of_sequence") + firstMessage.classList.add("middle_of_sequence") + } + if (firstMessageIsGenerated) { + secondMessage.classList.add("single_message") + } else { + secondMessage.classList.add("last_of_sequence") + } + } + } else if (!secondMessageIsGenerated) { + secondMessage.classList.add("single_message") + } + } + } else if (firstMessage) { + var firstMessageIsGenerated = firstMessage.classList.contains("generated_message") + if (secondMessage && !firstMessageIsGenerated) { + var secondMessageIsGenerated = secondMessage.classList.contains("generated_message") + var sequence_break = isSequenceBreak(firstMessage, secondMessage, false) + if (sequence_break) { + firstMessage.classList.add("single_message") + } else { + if (secondMessage.classList.contains("single_message")) { + secondMessage.classList.remove("single_message") + secondMessage.classList.add("last_of_sequence") + } else if (secondMessage.classList.contains("first_of_sequence")) { + secondMessage.classList.remove("first_of_sequence") + secondMessage.classList.add("middle_of_sequence") + } + if (secondMessageIsGenerated) { + firstMessage.classList.add("single_message") + } else { + firstMessage.classList.add("first_of_sequence") + } + } + } else if (!firstMessageIsGenerated) { + firstMessage.classList.add("single_message") + } + } +} + +/** + * Wrapper for addOrUpdateMessage. + * + * Add or update a message and make sure the scrollbar position + * is refreshed correctly + * + * @param message_object message to be added + */ +/* exported addMessage */ +function addMessage(message_object) { + if (!messages.lastChild) { + var block_wrapper = document.createElement("div") + messages.append(block_wrapper) + } + + exec_keeping_scroll_position(addOrUpdateMessage, [message_object, true, undefined, messages.lastChild]) +} + +/** + * Update a message that was previously added with addMessage and + * make sure the scrollbar position is refreshed correctly + * + * @param message_object message to be updated + */ +/* exported updateMessage */ +function updateMessage(message_object) { + var message_div = messages.querySelector("#message_" + message_object["id"]) + exec_keeping_scroll_position(addOrUpdateMessage, [message_object, false, undefined, message_div.parentNode]) +} + +/** + * Called whenever an image has finished loading. Check lazy loading status + * once all images have finished loading. + */ +function on_image_load_finished() { + imagesLoadingCounter-- + + if (!imagesLoadingCounter) { + /* This code is executed once all images have been loaded. */ + check_lazy_loading() + } +} + +/** + * Make sure at least initialScrollBufferFactor screens of messages are + * available in the DOM. + */ +function check_lazy_loading() { + if (!canLazyLoad) + return + if (messages.scrollHeight < initialScrollBufferFactor * messages.clientHeight + && historyBufferIndex !== historyBuffer.length) { + /* Not enough messages loaded, print a new batch. Enable isInitialLoading + as reloading a single batch might not be sufficient to fulfill our + criteria (we want to be called back again to check on that) */ + isInitialLoading = true + printHistoryPart(messages, 0) + isInitialLoading = false + } +} + +/** + * Display 'scrollBuffer' messages from history in passed div (reverse order). + * + * @param messages_div that should be modified + * @param fixedAt maintain scrollbar at the specified position + */ +function printHistoryPart(messages_div, fixedAt, allLoaded=true) { + if (historyBufferIndex === historyBuffer.length) { + return + } + /* If first element is a spinner, remove it */ + if (messages_div.firstChild && messages_div.firstChild.id === "lazyloading-icon") { + messages_div.removeChild(messages_div.firstChild) + } + + /* Elements are appended to a wrapper div. This div has no style + properties, it allows us to add all messages at once to the main + messages div. */ + var block_wrapper = document.createElement("div") + + messages_div.prepend(block_wrapper) + + for (var i = 0; i < scrollBuffer && historyBufferIndex < historyBuffer.length; ++historyBufferIndex && ++i) { + // TODO on-screen messages should be removed from the buffer + addOrUpdateMessage(historyBuffer[historyBuffer.length - 1 - historyBufferIndex], true, false, block_wrapper) + } + + var lastMessage = block_wrapper.lastChild + + updateSequencing(lastMessage, getNextInteraction(lastMessage)) + + var absoluteLastMessage = messages_div.lastChild.lastChild + if (absoluteLastMessage) { + absoluteLastMessage.classList.add("last_message") + } + + /* Add ellipsis (...) at the top if there are still messages to load */ + if (!allLoaded) { + var llicon = document.createElement("span") + llicon.id = "lazyloading-icon" + llicon.innerHTML = "<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"#888888\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path d=\"M0 0h24v24H0z\" fill=\"none\"/><path d=\"M6 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm12 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm-6 0c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z\"/></svg>" + messages_div.prepend(llicon) + } + + if (fixedAt !== undefined) { + /* update scrollbar position to take text-message -related + scrollHeight changes in account (not necessary to wait + for DOM redisplay in this case). Changes due to image + messages are handled in their onLoad callbacks. */ + back_to_scroll(fixedAt) + /* schedule a scrollbar position update for changes which + are neither handled by the previous call nor by onLoad + callbacks. This call is necessary but not sufficient, + dropping the previous call would result in visual + glitches during initial load. */ + setTimeout(function () {back_to_scroll(fixedAt)}, 0) + } + + if (!imagesLoadingCounter) { + setTimeout(check_lazy_loading, 0) + } +} + +function hideMessagesDiv() +{ + if (!messages.classList.contains("fade")) { + messages.classList.add("fade") + } +} + +function showMessagesDiv() +{ + if (messages.classList.contains("fade")) { + messages.classList.remove("fade") + } +} + +/** + * Set history buffer, initialize messages div and display a first batch + * of messages. + * + * Make sure that enough messages are displayed to fill initialScrollBufferFactor + * screens of messages (if enough messages are present in the conversation) + * + * @param messages_array should contain history to be printed + */ +/* exported printHistory */ +function printHistory(messages_array) +{ + historyBuffer = messages_array + + historyBufferIndex = 0 + isInitialLoading = true + printHistoryPart(messages, 0) + isInitialLoading = false + + canLazyLoad = true + if (use_qt) { + window.jsbridge.emitMessagesLoaded() + } else { + window.prompt("MESSAGES_LOADED") + } +} + + +/** + * Updates history buffer, used for lazy loading messages. + * Note: for swarm chat is used instead of printHistory, so + * reset of historyBufferIndex has been moved to clearMessages() + * + * @param messages_array should contain history to be printed + */ +/* exported printHistory */ +function updateHistory(messages_array, all_loaded) +{ + historyBuffer = messages_array + + printHistoryPart(messages, messages.scrollHeight, all_loaded) + canLazyLoad = true + + if (messages.scrollTop === 0) { + if (use_qt) { + window.jsbridge.loadMessages(scrollBuffer) + } else { + window.prompt(`LOAD_MESSAGES:${scrollBuffer}`) + } + } + + if (use_qt) { + window.jsbridge.emitMessagesLoaded() + } else { + window.prompt("MESSAGES_LOADED") + } +} + +/** + * Set the image for a given sender + * set_sender_image object should contain the following keys: + * - sender: the name of the sender + * - sender_image: base64 png encoding of the sender image + * + * @param set_sender_image_object sender image object as previously described + */ +/* exported setSenderImage */ +function setSenderImage(set_sender_image_object) +{ + if (use_qt) { + var sender_contact_method = set_sender_image_object["sender_contact_method"].replace(/@/g, "_").replace(/\./g, "_"), + sender_image = set_sender_image_object["sender_image"], + sender_image_id = "sender_image_" + sender_contact_method, + invite_sender_image_id = "invite_sender_image_" + sender_contact_method, + currentSenderImage = document.getElementById(sender_image_id), // Remove the currently set sender image + style, invite_style + + } else { + var sender_contact_method = set_sender_image_object["sender_contact_method"], + sender_image = set_sender_image_object["sender_image"], + sender_image_id = "sender_image_" + sender_contact_method, + invite_sender_image_id = "invite_sender_image_" + sender_contact_method, + currentSenderImage = document.getElementById(sender_image_id), // Remove the currently set sender image + style, invite_style + } + + if (currentSenderImage) { + currentSenderImage.parentNode.removeChild(currentSenderImage) + } + + // Create a new style element + style = document.createElement("style") + + style.type = "text/css" + style.id = sender_image_id + style.innerHTML = "." + sender_image_id + " {content: url(data:image/png;base64," + sender_image + ");height: 32px; width: 32px;}" + document.head.appendChild(style) + + invite_style = document.createElement("style") + + invite_style.type = "text/css" + invite_style.id = invite_sender_image_id + invite_style.innerHTML = "." + invite_sender_image_id + " {content: url(data:image/png;base64," + sender_image + ");height: 48px; width: 48px;}" + document.head.appendChild(invite_style) +} + +/** + * Show Typing indicator + */ +/* exported showTypingIndicator */ +function showTypingIndicator(contactUri, isTyping) { + var message_div + if (messages.lastChild) + message_div = messages.lastChild.querySelector("#message_typing") + else + return + + if (isTyping === 0) { + if (message_div) { + message_div.parentNode.removeChild(message_div) + } + } else if (!message_div) { + message_div = buildNewMessage({ + "id":"typing", + "type":"text", + "text":"", + "direction":"in", + "delivery_status":"", + "sender_contact_method": contactUri + }) + + var previousMessage = messages.lastChild.lastChild + messages.lastChild.appendChild(message_div) + computeSequencing(previousMessage, message_div, null, true) + if (previousMessage) { + previousMessage.classList.remove("last_message") + } + message_div.classList.add("last_message") + let msg_text = message_div.querySelector(".message_text") + msg_text.innerHTML = " \ + <div class=\"typing-indicator\"> \ + <span></span> \ + <span></span> \ + <span></span> \ + </div>" + } + updateMesPos() +} + +/** + * Copy Mouse Selected Text and return it + */ +function copy_text_selected() { + var selObj = document.getSelection() + var selectedText = selObj.toString() + return selectedText +} + +/** + * Check if text is selected by mouse + */ +function isTextSelected() { + + var selObj = document.getSelection() + var selectedText = selObj.toString() + + if (selectedText.length != 0) { + return true + } + return false +} + +/** + * add file (local file) to message area + */ +function addFile_path(path, name, size) { + var html = "<div class='file_wrapper' data-path='" + path + "'>" + + "<svg class='svgicon' version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 24 24' style='enable-background:new 0 0 24 24;' xml:space='preserve'>" + + "<path d='M14.2,2.3C14,2.1,13.7,2,13.4,2H5.5C4.8,2,4.3,2.5,4.3,3.2v6.3v1.6v9.7c0,0.7,0.5,1.2,1.2,1.2h13.1c0.7,0,1.2-0.5,1.2-1.2 V18V8.4c0-0.3-0.1-0.6-0.3-0.8L14.2,2.3z M18,7.7H14c0,0,0,0,0,0V3.7L18,7.7z M18.6,20.9C18.6,20.9,18.6,20.9,18.6,20.9l-13.1,0 c0,0,0,0,0,0v-9.7V9.5V3.2c0,0,0,0,0,0h7.4v4.5c0,0.7,0.5,1.2,1.2,1.2h4.5v9.2V20.9z'/>" + + "</svg>" + + "<div class='fileinfo'>" + + "<p>" + name + "</p>" + + "<p>" + size + "</p>" + + "</div >" + + "<button class='btn' onclick='remove(this)'>X</button>" + + "</div >" + // At first, visiblity can empty + if (sendContainer.style.display.length == 0 || sendContainer.style.display == "none") { + grow_send_container() + sendContainer.style.display = "flex" + } + //add html here since display is set to flex, image will change accordingly + sendContainer.innerHTML += html + updateMesPos() +} + +/** + * add image (base64 array) to message area + */ +function addImage_base64(base64) { + + var html = "<div class='img_wrapper'>" + + "<img src='data:image/png;base64," + base64 + "'/>" + + "<button class='btn' onclick='remove(this)'>X</button>" + + "</div >" + // At first, visiblity can empty + if (sendContainer.style.display.length == 0 || sendContainer.style.display == "none") { + grow_send_container() + sendContainer.style.display = "flex" + } + //add html here since display is set to flex, image will change accordingly + sendContainer.innerHTML += html + updateMesPos() +} + +/** + * add image (image path) to message area + */ +function addImage_path(path) { + + var html = "<div class='img_wrapper'>" + + "<img src='" + path +"'/>" + + "<button class='btn' onclick='remove(this)'>X</button>" + + "</div >" + // At first, visiblity can empty + if (sendContainer.style.display.length == 0 || sendContainer.style.display == "none") { + grow_send_container() + sendContainer.style.display = "flex" + } + //add html here since display is set to flex, image will change accordingly + sendContainer.innerHTML += html + updateMesPos() +} + +/** + * This function adjusts the body paddings so that that the data_transfer_send_container doesn't + * overlap messages when it grows. + */ +/* exported grow_send_container */ +function grow_send_container() { + exec_keeping_scroll_position(function () { + backToBottomBtnContainer.style.bottom = "calc(var(--messagebar-size) + 168px)" + }, []) + checkSendButton() +} + +/** + * This function adjusts the body paddings so that that the data_transfer_send_container will hide + * and recover padding bottom + */ +/* exported grow_send_container */ +function reduce_send_container() { + exec_keeping_scroll_position(function () { + sendContainer.innerHTML = "" + sendContainer.style.display = "none" + backToBottomBtnContainer.style.bottom = "var(--messagebar-size)" + //6em + }, []) + checkSendButton() +} + +// This function update the bottom of messages window whenever the send_interface changes size when the scroll is at the end +function updateMesPos() { + if (messages.scrollTop >= messages.scrollHeight - messages.clientHeight - scrollDetectionThresh) { + back_to_bottom() + } + checkSendButton() +} + +// Remove current cancel button division and hide the sendContainer +function remove(e) { + e.parentNode.parentNode.removeChild(e.parentNode) + if (sendContainer.innerHTML.length == 0) { + reduce_send_container() + } +} + +// It's called in qt qwebengine +function pasteKeyDetected(e) { + e.preventDefault() + window.jsbridge.emitPasteKeyDetected() +} + +// Set the curser to a target position +function setCaretPosition(elem, caretPos) { + var range + + if (elem.createTextRange) { + range = elem.createTextRange() + range.move("character", caretPos) + range.select() + } else { + elem.focus() + if (elem.selectionStart !== undefined) { + elem.setSelectionRange(caretPos, caretPos) + } + } +} + +function replaceText() { + navigator.clipboard.readText() + .then(text => { + var input = messageBarInput + var currentContent = input.value + var start = input.selectionStart + var end = input.selectionEnd + var output = [currentContent.slice(0, start), text, currentContent.slice(end)].join("") + input.value = output + setCaretPosition(input, start + text.length) + grow_text_area() + }) + .catch(err => { + console.error("Failed to read clipboard contents: ", err) + }) +} + +/** + * Change theme + * @param theme The dark theme + */ +function setTheme(theme) { + let root = document.documentElement + root.setAttribute("style", "\ + --jami-light-blue: rgba(59, 193, 211, 0.3);\ + --jami-dark-blue: #003b4e;\ + --jami-green: #1ed0a8;\ + --jami-green-hover: #1f8b4c;\ + --jami-red: #dc2719;\ + --jami-red-hover: #b02e2c;\ + --text-color: black;\ + --timestamp-color: #333;\ + --message-out-bg: #cfd8dc;\ + --message-out-txt: black;\ + --message-in-bg: #fdfdfd;\ + --message-in-txt: black;\ + --file-in-timestamp-color: #555;\ + --file-out-timestamp-color: #555;\ + --bg-color: #f2f2f2;\ + --navbar-height: 40px;\ + --navbar-padding-top: 8px;\ + --navbar-padding-bottom: var(--navbar-padding-top);\ + --textarea-max-height: 150px;\ + --placeholder-text-color: #d3d3d3;\ + --action-icon-color: var(--jami-dark-blue);\ + --deactivated-icon-color: #BEBEBE;\ + --action-icon-hover-color: var(--jami-light-blue);\ + --action-critical-icon-hover-color: rgba(211, 77, 59, 0.3);\ + --action-critical-icon-press-color: rgba(211, 77, 59, 0.5);\ + --action-critical-icon-color: #4E1300;\ + --action-icon-press-color: rgba(59, 193, 211, 0.5);\ + --invite-hover-color: white;\ + --bg-text-input: white;\ + ") + if (theme != "") { + root.setAttribute("style", theme) + } +} + +/** + * Get the content of the send message text field as a string. + * This should be called and the client should wait for + * saveSendMessageContent before calling clearSendMessageContent + * and printHistory when changing conversations. + * + */ +/* exported requestSendMessageContent */ +function requestSendMessageContent() { + if (use_qt) { + window.jsbridge.saveSendMessageContent(messageBarInput.value) + } else { + window.prompt("SAVE:" + messageBarInput.value) + } +} + +/** + * Sets the content of the send message text field. + * Use an empty string to clear. + * + * * @param contentStr the content + */ +/* exported setSendMessageContent */ +function setSendMessageContent(contentStr) { + messageBarInput.value = contentStr + // Do not grow if there are no messages loaded + if (historyBuffer.length !== 0) + grow_text_area() + reduce_send_container() +} + +function checkSendButton() { + sendButton.style.display = (messageBarInput.value.length > 0 + || sendContainer.innerHTML.length > 0) + ? "block" : "none" +} diff --git a/src/libclient/web-chatview/emoji.css b/src/libclient/web-chatview/emoji.css new file mode 100644 index 0000000000000000000000000000000000000000..8c6e111a8b7dfe701d1d715846606f96229d9d4c --- /dev/null +++ b/src/libclient/web-chatview/emoji.css @@ -0,0 +1,494 @@ +@keyframes show { + 0% { + opacity: 0; + transform: scale3d(0.8, 0.8, 0.8); + } + + 50% { + transform: scale3d(1.05, 1.05, 1.05); + } + + 100% { + transform: scale3d(1, 1, 1); + } +} + +@keyframes hide { + 0% { + opacity: 1; + transform: scale3d(1, 1, 1); + } + + 100% { + opacity: 0; + transform: scale3d(0.8, 0.8, 0.8); + } +} + +@keyframes grow { + 0% { + opacity: 0; + transform: scale3d(0.8, 0.8, 0.8); + } + + 100% { + opacity: 1; + transform: scale3d(1, 1, 1); + } +} + +@keyframes shrink { + 0% { + opacity: 1; + transform: scale3d(1, 1, 1); + } + + 100% { + opacity: 0; + transform: scale3d(0.8, 0.8, 0.8); + } +} + +@keyframes fade-in { + 0% { opacity: 0; } + 100% { opacity: 1; } +} + +@keyframes fade-out { + 0% { opacity: 1; } + 100% { opacity: 0; } +} + +.emoji-picker { + --animation-duration: 0.2s; + --animation-easing: ease-in-out; + + --emoji-size: 1.8em; + --emoji-size-multiplier: 1.5; + --emoji-preview-size: 2em; + --emoji-per-row: 8; + --row-count: 6; + + --content-height: calc((var(--emoji-size) * var(--emoji-size-multiplier)) * var(--row-count) + var(--category-name-size) + var(--category-button-height) + 0.5em); + + --category-name-size: 0.85em; + + --category-button-height: 2em; + --category-button-size: 1.1em; + --category-border-bottom-size: 4px; + + --focus-indicator-color: #999999; + + --search-height: 2em; + + --blue-color: #4F81E5; + + --border-color: #CCCCCC; + --background-color: #FFFFFF; + --text-color: #000000; + --secondary-text-color: #666666; + --hover-color: #E8F4F9; + --search-focus-border-color: var(--blue-color); + --search-icon-color: #CCCCCC; + --overlay-background-color: rgba(0, 0, 0, 0.8); + --popup-background-color: #FFFFFF; + --category-button-color: #666666; + --category-button-active-color: var(--blue-color); + + --dark-border-color: #666666; + --dark-background-color: #333333; + --dark-text-color: #FFFFFF; + --dark-secondary-text-color: #999999; + --dark-hover-color: #666666; + --dark-search-background-color: #666666; + --dark-search-border-color: #999999; + --dark-search-placeholder-color: #999999; + --dark-search-focus-border-color: #DBE5F9; + --dark-popup-background-color: #333333; + --dark-category-button-color: #FFFFFF; + + --font: Arial, Helvetica, sans-serif; + --font-size: 16px; +} + +.emoji-picker { + font-size: var(--font-size); + border: 1px solid var(--border-color); + border-radius: 5px; + background: var(--background-color); + width: calc(var(--emoji-per-row) * var(--emoji-size) * var(--emoji-size-multiplier) + 1em + 1.5rem); + font-family: var(--font); + overflow: hidden; + animation: show var(--animation-duration) var(--animation-easing); +} + +.emoji-picker * { + font-family: var(--font); + box-sizing: content-box; +} + +.emoji-picker__overlay { + background: rgba(0, 0, 0, 0.75); + z-index: 1000; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +.emoji-picker.hiding { + animation: hide var(--animation-duration) var(--animation-easing); +} + +.emoji-picker.dark { + background: var(--dark-background-color); + color: var(--dark-text-color); + border-color: var(--dark-border-color); +} + +.emoji-picker__content { + padding: 0.5em; + height: var(--content-height); + position: relative; +} + +.emoji-picker__preview { + height: var(--emoji-preview-size); + padding: 0.5em; + border-top: 1px solid var(--border-color); + display: flex; + flex-direction: row; + align-items: center; +} + +.emoji-picker.dark .emoji-picker__preview { + border-top-color: var(--dark-border-color); +} + +.emoji-picker__preview-emoji { + font-size: var(--emoji-preview-size); + margin-right: 0.25em; + font-family: "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "Apple Color Emoji", "Twemoji Mozilla", "Noto Color Emoji", "EmojiOne Color", "Android Emoji"; +} + +.emoji-picker__preview-emoji img.emoji { + height: 1em; + width: 1em; + margin: 0 .05em 0 .1em; + vertical-align: -0.1em; +} + +.emoji-picker__preview-name { + color: var(--text-color); + font-size: 0.85em; + overflow-wrap: break-word; + word-break: break-all; +} + +.emoji-picker.dark .emoji-picker__preview-name { + color: var(--dark-text-color); +} + +.emoji-picker__container { + display: grid; + justify-content: center; + grid-template-columns: repeat(var(--emoji-per-row), calc(var(--emoji-size) * var(--emoji-size-multiplier))); + grid-auto-rows: calc(var(--emoji-size) * var(--emoji-size-multiplier)); +} + +.emoji-picker__container.search-results { + height: var(--content-height); + overflow-y: auto; +} + +.emoji-picker__custom-emoji { + width: 1em; + height: 1em; +} + +.emoji-picker__emoji { + background: transparent; + border: none; + cursor: pointer; + overflow: hidden; + font-size: var(--emoji-size); + width: 1.5em; + height: 1.5em; + padding: 0; + margin: 0; + outline: none; + font-family: "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "Apple Color Emoji", "Twemoji Mozilla", "Noto Color Emoji", "EmojiOne Color", "Android Emoji"; + display: inline-flex; + align-items: center; + justify-content: center; +} + +.emoji-picker__emoji img.emoji { + height: 1em; + width: 1em; + margin: 0 .05em 0 .1em; + vertical-align: -0.1em; +} + +.emoji-picker__emoji:focus, .emoji-picker__emoji:hover { + background: var(--hover-color); +} + +.emoji-picker__emoji:focus { + outline: 1px dotted var(--focus-indicator-color); +} + +.emoji-picker.dark .emoji-picker__emoji:focus, .emoji-picker.dark .emoji-picker__emoji:hover { + background: var(--dark-hover-color); +} + +.emoji-picker__plugin-container { + margin: 0.5em; + display: flex; + flex-direction: row; +} + +.emoji-picker__search-container { + margin: 0.5em; + position: relative; + height: var(--search-height); + display: flex; +} + +.emoji-picker__search { + box-sizing: border-box; + width: 100%; + border-radius: 3px; + border: 1px solid var(--border-color); + padding-right: 2em; + padding: 0.5em 2.25em 0.5em 0.5em; + font-size: 0.85em; + outline: none; +} + +.emoji-picker.dark .emoji-picker__search { + background: var(--dark-search-background-color); + color: var(--dark-text-color); + border-color: var(--dark-search-border-color); +} + +.emoji-picker.dark .emoji-picker__search::placeholder { + color: var(--dark-search-placeholder-color); +} + +.emoji-picker__search:focus { + border: 1px solid var(--search-focus-border-color); +} + +.emoji-picker.dark .emoji-picker__search:focus { + border-color: var(--dark-search-focus-border-color); +} + +.emoji-picker__search-icon { + position: absolute; + color: var(--search-icon-color); + width: 1em; + height: 1em; + right: 0.75em; + top: calc(50% - 0.5em); +} + +.emoji-picker__search-icon img { + width: 1em; + height: 1em; +} + +.emoji-picker__search-not-found { + color: var(--secondary-text-color); + text-align: center; + height: 100%; + display: flex; + flex-direction: column; + justify-content: center; +} + +.emoji-picker__search-not-found h2 { + color: var(--secondary-text-color); +} + +.emoji-picker.dark .emoji-picker__search-not-found { + color: var(--dark-secondary-text-color); +} + +.emoji-picker.dark .emoji-picker__search-not-found h2 { + color: var(--dark-secondary-text-color); +} + +.emoji-picker__search-not-found-icon { + font-size: 3em; +} + +.emoji-picker__search-not-found-icon img { + width: 1em; + height: 1em; +} + +.emoji-picker__search-not-found h2 { + margin: 0.5em 0; + font-size: 1em; +} + +.emoji-picker__variant-overlay { + background: var(--overlay-background-color); + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + border-radius: 5px; + display: flex; + flex-direction: column; + justify-content: center; + animation: fade-in var(--animation-duration) var(--animation-easing); +} + +.emoji-picker__variant-overlay.hiding { + animation: fade-out var(--animation-duration) var(--animation-easing); +} + +.emoji-picker__variant-popup { + background: var(--popup-background-color); + margin: 0.5em; + padding: 0.5em; + text-align: center; + border-radius: 5px; + animation: grow var(--animation-duration) var(--animation-easing); + user-select: none; +} + +.emoji-picker__variant-overlay.hiding .emoji-picker__variant-popup { + animation: shrink var(--animation-duration) var(--animation-easing); +} + +.emoji-picker.dark .emoji-picker__variant-popup { + background: var(--dark-popup-background-color); +} + +.emoji-picker__emojis { + overflow-y: auto; + position: relative; + height: calc((var(--emoji-size) * var(--emoji-size-multiplier)) * var(--row-count) + var(--category-name-size)); +} + +.emoji-picker__emojis.hiding { + animation: fade-out 0.05s var(--animation-easing); +} + +.emoji-picker__emojis h2.emoji-picker__category-name { + font-size: 0.85em; + color: var(--secondary-text-color); + text-transform: uppercase; + margin: 0.25em 0; + text-align: left; +} + +.emoji-picker.dark h2.emoji-picker__category-name { + color: var(--dark-secondary-text-color); +} + +.emoji-picker__category-buttons { + display: flex; + flex-direction: row; + justify-content: space-around; + height: var(--category-button-height); + margin-bottom: 0.5em; +} + +button.emoji-picker__category-button { + flex-grow: 1; + background: transparent; + padding: 0; + border: none; + cursor: pointer; + font-size: var(--category-button-size); + vertical-align: middle; + color: var(--category-button-color); + border-bottom: var(--category-border-bottom-size) solid transparent; + outline: none; +} + +button.emoji-picker__category-button img { + width: var(--category-button-size); + height: var(--category-button-size); +} + +.emoji-picker.keyboard button.emoji-picker__category-button:focus { + outline: 1px dotted var(--focus-indicator-color); +} + +.emoji-picker.dark button.emoji-picker__category-button.active { + color: var(--category-button-active-color); +} + +.emoji-picker.dark button.emoji-picker__category-button { + color: var(--dark-category-button-color); +} + +button.emoji-picker__category-button.active { + color: var(--category-button-active-color); + border-bottom: var(--category-border-bottom-size) solid var(--category-button-active-color); +} + +@media (prefers-color-scheme: dark) { + .emoji-picker.auto { + background: var(--dark-background-color); + color: var(--dark-text-color); + border-color: var(--dark-border-color); + } + + .emoji-picker.auto .emoji-picker__preview { + border-top-color: var(--dark-border-color); + } + + .emoji-picker.auto .emoji-picker__preview-name { + color: var(--dark-text-color); + } + + .emoji-picker.auto button.emoji-picker__category-button { + color: var(--dark-category-button-color); + } + + .emoji-picker.auto button.emoji-picker__category-button.active { + color: var(--category-button-active-color); + } + + .emoji-picker.auto .emoji-picker__emoji:focus, .emoji-picker.auto .emoji-picker__emoji:hover { + background: var(--dark-hover-color); + } + + .emoji-picker.auto .emoji-picker__search { + background: var(--dark-search-background-color); + color: var(--dark-text-color); + border-color: var(--dark-search-border-color); + } + + .emoji-picker.auto h2.emoji-picker__category-name { + color: var(--dark-secondary-text-color); + } + + .emoji-picker.auto .emoji-picker__search::placeholder { + color: var(--dark-search-placeholder-color); + } + + .emoji-picker.auto .emoji-picker__search:focus { + border-color: var(--dark-search-focus-border-color); + } + + .emoji-picker.auto .emoji-picker__search-not-found { + color: var(--dark-secondary-text-color); + } + + .emoji-picker.auto .emoji-picker__search-not-found h2 { + color: var(--dark-secondary-text-color); + } + + .emoji-picker.auto .emoji-picker__variant-popup { + background: var(--dark-popup-background-color); + } +} \ No newline at end of file diff --git a/src/libclient/web-chatview/emoji.js b/src/libclient/web-chatview/emoji.js new file mode 100644 index 0000000000000000000000000000000000000000..1d7b13c5c948a047f1f537072243556e3b70b7b5 --- /dev/null +++ b/src/libclient/web-chatview/emoji.js @@ -0,0 +1,19 @@ +/** + * Skipped minification because the original files appears to be already minified. + * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files + */ +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH +REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, +INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +PERFORMANCE OF THIS SOFTWARE. +***************************************************************************** */ +function e(e, o, n, i) { return new (n || (n = Promise))((function (a, r) { function t(e) { try { m(i.next(e)) } catch (e) { r(e) } } function s(e) { try { m(i.throw(e)) } catch (e) { r(e) } } function m(e) { var o; e.done ? a(e.value) : (o = e.value, o instanceof n ? o : new n((function (e) { e(o) }))).then(t, s) } m((i = i.apply(e, o || [])).next()) })) } !function (e, o) { void 0 === o && (o = {}); var n = o.insertAt; if (e && "undefined" != typeof document) { var i = document.head || document.getElementsByTagName("head")[0], a = document.createElement("style"); a.type = "text/css", "top" === n && i.firstChild ? i.insertBefore(a, i.firstChild) : i.appendChild(a), a.styleSheet ? a.styleSheet.cssText = e : a.appendChild(document.createTextNode(e)) } }('@keyframes show {\n 0% {\n opacity: 0;\n transform: scale3d(0.8, 0.8, 0.8);\n }\n\n 50% {\n transform: scale3d(1.05, 1.05, 1.05);\n }\n\n 100% {\n transform: scale3d(1, 1, 1);\n }\n}\n\n@keyframes hide {\n 0% {\n opacity: 1;\n transform: scale3d(1, 1, 1);\n }\n\n 100% {\n opacity: 0;\n transform: scale3d(0.8, 0.8, 0.8);\n }\n}\n\n@keyframes grow {\n 0% {\n opacity: 0;\n transform: scale3d(0.8, 0.8, 0.8); \n }\n\n 100% { \n opacity: 1;\n transform: scale3d(1, 1, 1); \n }\n}\n\n@keyframes shrink {\n 0% { \n opacity: 1;\n transform: scale3d(1, 1, 1);\n }\n\n 100% { \n opacity: 0;\n transform: scale3d(0.8, 0.8, 0.8); \n }\n}\n\n@keyframes fade-in {\n 0% { opacity: 0; }\n 100% { opacity: 1; }\n}\n\n@keyframes fade-out {\n 0% { opacity: 1; }\n 100% { opacity: 0; }\n}\n\n.emoji-picker {\n --animation-duration: 0.2s;\n --animation-easing: ease-in-out;\n\n --emoji-size: 1.8em;\n --emoji-size-multiplier: 1.5;\n --emoji-preview-size: 2em;\n --emoji-per-row: 8;\n --row-count: 6;\n\n --content-height: calc((var(--emoji-size) * var(--emoji-size-multiplier)) * var(--row-count) + var(--category-name-size) + var(--category-button-height) + 0.5em);\n\n --category-name-size: 0.85em;\n\n --category-button-height: 2em;\n --category-button-size: 1.1em;\n --category-border-bottom-size: 4px;\n\n --focus-indicator-color: #999999;\n\n --search-height: 2em;\n\n --blue-color: #4F81E5;\n\n --border-color: #CCCCCC;\n --background-color: #FFFFFF;\n --text-color: #000000;\n --secondary-text-color: #666666;\n --hover-color: #E8F4F9;\n --search-focus-border-color: var(--blue-color);\n --search-icon-color: #CCCCCC;\n --overlay-background-color: rgba(0, 0, 0, 0.8);\n --popup-background-color: #FFFFFF;\n --category-button-color: #666666;\n --category-button-active-color: var(--blue-color);\n\n --dark-border-color: #666666;\n --dark-background-color: #333333;\n --dark-text-color: #FFFFFF;\n --dark-secondary-text-color: #999999;\n --dark-hover-color: #666666;\n --dark-search-background-color: #666666;\n --dark-search-border-color: #999999;\n --dark-search-placeholder-color: #999999;\n --dark-search-focus-border-color: #DBE5F9;\n --dark-popup-background-color: #333333;\n --dark-category-button-color: #FFFFFF;\n\n --font: Arial, Helvetica, sans-serif;\n --font-size: 16px;\n}\n\n.emoji-picker {\n font-size: var(--font-size);\n border: 1px solid var(--border-color);\n border-radius: 5px;\n background: var(--background-color);\n width: calc(var(--emoji-per-row) * var(--emoji-size) * var(--emoji-size-multiplier) + 1em + 1.5rem);\n font-family: var(--font);\n overflow: hidden;\n animation: show var(--animation-duration) var(--animation-easing);\n}\n\n.emoji-picker * {\n font-family: var(--font);\n box-sizing: content-box;\n}\n\n.emoji-picker__overlay {\n background: rgba(0, 0, 0, 0.75);\n z-index: 1000;\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n}\n\n.emoji-picker.hiding {\n animation: hide var(--animation-duration) var(--animation-easing);\n}\n\n.emoji-picker.dark {\n background: var(--dark-background-color);\n color: var(--dark-text-color);\n border-color: var(--dark-border-color);\n}\n\n.emoji-picker__content {\n padding: 0.5em;\n height: var(--content-height);\n position: relative;\n}\n\n.emoji-picker__preview {\n height: var(--emoji-preview-size);\n padding: 0.5em;\n border-top: 1px solid var(--border-color);\n display: flex;\n flex-direction: row;\n align-items: center;\n}\n\n.emoji-picker.dark .emoji-picker__preview {\n border-top-color: var(--dark-border-color);\n}\n\n.emoji-picker__preview-emoji {\n font-size: var(--emoji-preview-size);\n margin-right: 0.25em;\n font-family: "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "Apple Color Emoji", "Twemoji Mozilla", "Noto Color Emoji", "EmojiOne Color", "Android Emoji";\n}\n\n.emoji-picker__preview-emoji img.emoji {\n height: 1em;\n width: 1em;\n margin: 0 .05em 0 .1em;\n vertical-align: -0.1em;\n}\n\n.emoji-picker__preview-name {\n color: var(--text-color);\n font-size: 0.85em;\n overflow-wrap: break-word;\n word-break: break-all;\n}\n\n.emoji-picker.dark .emoji-picker__preview-name {\n color: var(--dark-text-color);\n}\n\n.emoji-picker__container {\n display: grid;\n justify-content: center;\n grid-template-columns: repeat(var(--emoji-per-row), calc(var(--emoji-size) * var(--emoji-size-multiplier)));\n grid-auto-rows: calc(var(--emoji-size) * var(--emoji-size-multiplier));\n}\n\n.emoji-picker__container.search-results {\n height: var(--content-height);\n overflow-y: auto;\n}\n\n.emoji-picker__custom-emoji {\n width: 1em;\n height: 1em;\n}\n\n.emoji-picker__emoji {\n background: transparent;\n border: none;\n cursor: pointer;\n overflow: hidden;\n font-size: var(--emoji-size);\n width: 1.5em;\n height: 1.5em;\n padding: 0;\n margin: 0;\n outline: none;\n font-family: "Segoe UI Emoji", "Segoe UI Symbol", "Segoe UI", "Apple Color Emoji", "Twemoji Mozilla", "Noto Color Emoji", "EmojiOne Color", "Android Emoji";\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n.emoji-picker__emoji img.emoji {\n height: 1em;\n width: 1em;\n margin: 0 .05em 0 .1em;\n vertical-align: -0.1em;\n}\n\n.emoji-picker__emoji:focus, .emoji-picker__emoji:hover {\n background: var(--hover-color);\n}\n\n.emoji-picker__emoji:focus {\n outline: 1px dotted var(--focus-indicator-color);\n}\n\n.emoji-picker.dark .emoji-picker__emoji:focus, .emoji-picker.dark .emoji-picker__emoji:hover {\n background: var(--dark-hover-color);\n}\n\n.emoji-picker__plugin-container {\n margin: 0.5em;\n display: flex;\n flex-direction: row;\n}\n\n.emoji-picker__search-container {\n margin: 0.5em;\n position: relative;\n height: var(--search-height);\n display: flex;\n}\n\n.emoji-picker__search {\n box-sizing: border-box;\n width: 100%;\n border-radius: 3px;\n border: 1px solid var(--border-color);\n padding-right: 2em;\n padding: 0.5em 2.25em 0.5em 0.5em;\n font-size: 0.85em;\n outline: none;\n}\n\n.emoji-picker.dark .emoji-picker__search {\n background: var(--dark-search-background-color);\n color: var(--dark-text-color);\n border-color: var(--dark-search-border-color);\n}\n\n.emoji-picker.dark .emoji-picker__search::placeholder {\n color: var(--dark-search-placeholder-color);\n}\n\n.emoji-picker__search:focus {\n border: 1px solid var(--search-focus-border-color);\n}\n\n.emoji-picker.dark .emoji-picker__search:focus {\n border-color: var(--dark-search-focus-border-color);\n}\n\n.emoji-picker__search-icon {\n position: absolute;\n color: var(--search-icon-color);\n width: 1em;\n height: 1em;\n right: 0.75em;\n top: calc(50% - 0.5em);\n}\n\n.emoji-picker__search-icon img {\n width: 1em;\n height: 1em;\n}\n\n.emoji-picker__search-not-found {\n color: var(--secondary-text-color);\n text-align: center;\n height: 100%;\n display: flex;\n flex-direction: column;\n justify-content: center;\n}\n\n.emoji-picker__search-not-found h2 {\n color: var(--secondary-text-color);\n}\n\n.emoji-picker.dark .emoji-picker__search-not-found {\n color: var(--dark-secondary-text-color);\n}\n\n.emoji-picker.dark .emoji-picker__search-not-found h2 {\n color: var(--dark-secondary-text-color);\n}\n\n.emoji-picker__search-not-found-icon {\n font-size: 3em;\n}\n\n.emoji-picker__search-not-found-icon img {\n width: 1em;\n height: 1em;\n}\n\n.emoji-picker__search-not-found h2 {\n margin: 0.5em 0;\n font-size: 1em;\n}\n\n.emoji-picker__variant-overlay {\n background: var(--overlay-background-color);\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n border-radius: 5px;\n display: flex;\n flex-direction: column;\n justify-content: center;\n animation: fade-in var(--animation-duration) var(--animation-easing);\n}\n\n.emoji-picker__variant-overlay.hiding {\n animation: fade-out var(--animation-duration) var(--animation-easing);\n}\n\n.emoji-picker__variant-popup {\n background: var(--popup-background-color);\n margin: 0.5em;\n padding: 0.5em;\n text-align: center;\n border-radius: 5px;\n animation: grow var(--animation-duration) var(--animation-easing);\n user-select: none;\n}\n\n.emoji-picker__variant-overlay.hiding .emoji-picker__variant-popup {\n animation: shrink var(--animation-duration) var(--animation-easing);\n}\n\n.emoji-picker.dark .emoji-picker__variant-popup {\n background: var(--dark-popup-background-color);\n}\n\n.emoji-picker__emojis {\n overflow-y: auto;\n position: relative;\n height: calc((var(--emoji-size) * var(--emoji-size-multiplier)) * var(--row-count) + var(--category-name-size));\n}\n\n.emoji-picker__emojis.hiding {\n animation: fade-out 0.05s var(--animation-easing);\n}\n\n.emoji-picker__emojis h2.emoji-picker__category-name {\n font-size: 0.85em;\n color: var(--secondary-text-color);\n text-transform: uppercase;\n margin: 0.25em 0;\n text-align: left;\n}\n\n.emoji-picker.dark h2.emoji-picker__category-name {\n color: var(--dark-secondary-text-color);\n}\n\n.emoji-picker__category-buttons {\n display: flex;\n flex-direction: row;\n justify-content: space-around;\n height: var(--category-button-height);\n margin-bottom: 0.5em;\n}\n\nbutton.emoji-picker__category-button {\n flex-grow: 1;\n background: transparent;\n padding: 0;\n border: none;\n cursor: pointer;\n font-size: var(--category-button-size);\n vertical-align: middle;\n color: var(--category-button-color);\n border-bottom: var(--category-border-bottom-size) solid transparent;\n outline: none;\n}\n\nbutton.emoji-picker__category-button img {\n width: var(--category-button-size);\n height: var(--category-button-size);\n}\n\n.emoji-picker.keyboard button.emoji-picker__category-button:focus {\n outline: 1px dotted var(--focus-indicator-color);\n}\n\n.emoji-picker.dark button.emoji-picker__category-button.active {\n color: var(--category-button-active-color);\n}\n\n.emoji-picker.dark button.emoji-picker__category-button {\n color: var(--dark-category-button-color);\n}\n\nbutton.emoji-picker__category-button.active {\n color: var(--category-button-active-color);\n border-bottom: var(--category-border-bottom-size) solid var(--category-button-active-color);\n}\n\n@media (prefers-color-scheme: dark) {\n .emoji-picker.auto {\n background: var(--dark-background-color);\n color: var(--dark-text-color);\n border-color: var(--dark-border-color);\n }\n\n .emoji-picker.auto .emoji-picker__preview {\n border-top-color: var(--dark-border-color);\n }\n\n .emoji-picker.auto .emoji-picker__preview-name {\n color: var(--dark-text-color);\n }\n\n .emoji-picker.auto button.emoji-picker__category-button {\n color: var(--dark-category-button-color);\n }\n\n .emoji-picker.auto button.emoji-picker__category-button.active {\n color: var(--category-button-active-color);\n }\n\n .emoji-picker.auto .emoji-picker__emoji:focus, .emoji-picker.auto .emoji-picker__emoji:hover {\n background: var(--dark-hover-color);\n }\n\n .emoji-picker.auto .emoji-picker__search {\n background: var(--dark-search-background-color);\n color: var(--dark-text-color);\n border-color: var(--dark-search-border-color);\n }\n \n .emoji-picker.auto h2.emoji-picker__category-name {\n color: var(--dark-secondary-text-color);\n }\n\n .emoji-picker.auto .emoji-picker__search::placeholder {\n color: var(--dark-search-placeholder-color);\n }\n\n .emoji-picker.auto .emoji-picker__search:focus {\n border-color: var(--dark-search-focus-border-color);\n }\n\n .emoji-picker.auto .emoji-picker__search-not-found {\n color: var(--dark-secondary-text-color);\n }\n\n .emoji-picker.auto .emoji-picker__search-not-found h2 {\n color: var(--dark-secondary-text-color);\n }\n\n .emoji-picker.auto .emoji-picker__variant-popup {\n background: var(--dark-popup-background-color);\n }\n}'); var o = ["input", "select", "textarea", "a[href]", "button", "[tabindex]", "audio[controls]", "video[controls]", '[contenteditable]:not([contenteditable="false"])'], n = o.join(","), i = "undefined" == typeof Element ? function () { } : Element.prototype.matches || Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector; function a(e, o) { o = o || {}; var a, t, s, d = [], g = [], u = e.querySelectorAll(n); for (o.includeContainer && i.call(e, n) && (u = Array.prototype.slice.apply(u)).unshift(e), a = 0; a < u.length; a++)r(t = u[a]) && (0 === (s = m(t)) ? d.push(t) : g.push({ documentOrder: a, tabIndex: s, node: t })); return g.sort(c).map((function (e) { return e.node })).concat(d) } function r(e) { return !(!t(e) || function (e) { return function (e) { return d(e) && "radio" === e.type }(e) && !function (e) { if (!e.name) return !0; var o = function (e) { for (var o = 0; o < e.length; o++)if (e[o].checked) return e[o] }(e.ownerDocument.querySelectorAll('input[type="radio"][name="' + e.name + '"]')); return !o || o === e }(e) }(e) || m(e) < 0) } function t(e) { return !(e.disabled || function (e) { return d(e) && "hidden" === e.type }(e) || function (e) { return null === e.offsetParent || "hidden" === getComputedStyle(e).visibility }(e)) } a.isTabbable = function (e) { if (!e) throw new Error("No node provided"); return !1 !== i.call(e, n) && r(e) }, a.isFocusable = function (e) { if (!e) throw new Error("No node provided"); return !1 !== i.call(e, s) && t(e) }; var s = o.concat("iframe").join(","); function m(e) { var o = parseInt(e.getAttribute("tabindex"), 10); return isNaN(o) ? function (e) { return "true" === e.contentEditable }(e) ? 0 : e.tabIndex : o } function c(e, o) { return e.tabIndex === o.tabIndex ? e.documentOrder - o.documentOrder : e.tabIndex - o.tabIndex } function d(e) { return "INPUT" === e.tagName } var g, u = a, l = function () { for (var e = {}, o = 0; o < arguments.length; o++) { var n = arguments[o]; for (var i in n) v.call(n, i) && (e[i] = n[i]) } return e }, v = Object.prototype.hasOwnProperty; var f, y = (f = [], { activateTrap: function (e) { if (f.length > 0) { var o = f[f.length - 1]; o !== e && o.pause() } var n = f.indexOf(e); -1 === n || f.splice(n, 1), f.push(e) }, deactivateTrap: function (e) { var o = f.indexOf(e); -1 !== o && f.splice(o, 1), f.length > 0 && f[f.length - 1].unpause() } }); function j(e) { return setTimeout(e, 0) } var h = function (e, o) { var n = document, i = "string" == typeof e ? n.querySelector(e) : e, a = l({ returnFocusOnDeactivate: !0, escapeDeactivates: !0 }, o), r = { firstTabbableNode: null, lastTabbableNode: null, nodeFocusedBeforeActivation: null, mostRecentlyFocusedNode: null, active: !1, paused: !1 }, t = { activate: function (e) { if (r.active) return; w(), r.active = !0, r.paused = !1, r.nodeFocusedBeforeActivation = n.activeElement; var o = e && e.onActivate ? e.onActivate : a.onActivate; o && o(); return m(), t }, deactivate: s, pause: function () { if (r.paused || !r.active) return; r.paused = !0, c() }, unpause: function () { if (!r.paused || !r.active) return; r.paused = !1, w(), m() } }; return t; function s(e) { if (r.active) { clearTimeout(g), c(), r.active = !1, r.paused = !1, y.deactivateTrap(t); var o = e && void 0 !== e.onDeactivate ? e.onDeactivate : a.onDeactivate; return o && o(), (e && void 0 !== e.returnFocus ? e.returnFocus : a.returnFocusOnDeactivate) && j((function () { var e; k((e = r.nodeFocusedBeforeActivation, d("setReturnFocus") || e)) })), t } } function m() { if (r.active) return y.activateTrap(t), g = j((function () { k(v()) })), n.addEventListener("focusin", h, !0), n.addEventListener("mousedown", f, { capture: !0, passive: !1 }), n.addEventListener("touchstart", f, { capture: !0, passive: !1 }), n.addEventListener("click", b, { capture: !0, passive: !1 }), n.addEventListener("keydown", p, { capture: !0, passive: !1 }), t } function c() { if (r.active) return n.removeEventListener("focusin", h, !0), n.removeEventListener("mousedown", f, !0), n.removeEventListener("touchstart", f, !0), n.removeEventListener("click", b, !0), n.removeEventListener("keydown", p, !0), t } function d(e) { var o = a[e], i = o; if (!o) return null; if ("string" == typeof o && !(i = n.querySelector(o))) throw new Error("`" + e + "` refers to no known node"); if ("function" == typeof o && !(i = o())) throw new Error("`" + e + "` did not return a node"); return i } function v() { var e; if (!(e = null !== d("initialFocus") ? d("initialFocus") : i.contains(n.activeElement) ? n.activeElement : r.firstTabbableNode || d("fallbackFocus"))) throw new Error("Your focus-trap needs to have at least one focusable element"); return e } function f(e) { i.contains(e.target) || (a.clickOutsideDeactivates ? s({ returnFocus: !u.isFocusable(e.target) }) : a.allowOutsideClick && a.allowOutsideClick(e) || e.preventDefault()) } function h(e) { i.contains(e.target) || e.target instanceof Document || (e.stopImmediatePropagation(), k(r.mostRecentlyFocusedNode || v())) } function p(e) { if (!1 !== a.escapeDeactivates && function (e) { return "Escape" === e.key || "Esc" === e.key || 27 === e.keyCode }(e)) return e.preventDefault(), void s(); (function (e) { return "Tab" === e.key || 9 === e.keyCode })(e) && function (e) { if (w(), e.shiftKey && e.target === r.firstTabbableNode) return e.preventDefault(), void k(r.lastTabbableNode); if (!e.shiftKey && e.target === r.lastTabbableNode) e.preventDefault(), k(r.firstTabbableNode) }(e) } function b(e) { a.clickOutsideDeactivates || i.contains(e.target) || a.allowOutsideClick && a.allowOutsideClick(e) || (e.preventDefault(), e.stopImmediatePropagation()) } function w() { var e = u(i); r.firstTabbableNode = e[0] || v(), r.lastTabbableNode = e[e.length - 1] || v() } function k(e) { e !== n.activeElement && (e && e.focus ? (e.focus(), r.mostRecentlyFocusedNode = e, function (e) { return e.tagName && "input" === e.tagName.toLowerCase() && "function" == typeof e.select }(e) && e.select()) : k(v())) } }; function p() { } p.prototype = { on: function (e, o, n) { var i = this.e || (this.e = {}); return (i[e] || (i[e] = [])).push({ fn: o, ctx: n }), this }, once: function (e, o, n) { var i = this; function a() { i.off(e, a), o.apply(n, arguments) } return a._ = o, this.on(e, a, n) }, emit: function (e) { for (var o = [].slice.call(arguments, 1), n = ((this.e || (this.e = {}))[e] || []).slice(), i = 0, a = n.length; i < a; i++)n[i].fn.apply(n[i].ctx, o); return this }, off: function (e, o) { var n = this.e || (this.e = {}), i = n[e], a = []; if (i && o) for (var r = 0, t = i.length; r < t; r++)i[r].fn !== o && i[r].fn._ !== o && a.push(i[r]); return a.length ? n[e] = a : delete n[e], this } }; var b = p; function w(e) { var o = e.getBoundingClientRect(); return { width: o.width, height: o.height, top: o.top, right: o.right, bottom: o.bottom, left: o.left, x: o.left, y: o.top } } function k(e) { if ("[object Window]" !== e.toString()) { var o = e.ownerDocument; return o ? o.defaultView : window } return e } function x(e) { var o = k(e); return { scrollLeft: o.pageXOffset, scrollTop: o.pageYOffset } } function C(e) { return e instanceof k(e).Element || e instanceof Element } function E(e) { return e instanceof k(e).HTMLElement || e instanceof HTMLElement } function _(e) { return e ? (e.nodeName || "").toLowerCase() : null } function z(e) { return (C(e) ? e.ownerDocument : e.document).documentElement } function O(e) { return w(z(e)).left + x(e).scrollLeft } function I(e) { return k(e).getComputedStyle(e) } function S(e) { var o = I(e), n = o.overflow, i = o.overflowX, a = o.overflowY; return /auto|scroll|overlay|hidden/.test(n + a + i) } function P(e, o, n) { void 0 === n && (n = !1); var i, a, r = z(o), t = w(e), s = { scrollLeft: 0, scrollTop: 0 }, m = { x: 0, y: 0 }; return n || (("body" !== _(o) || S(r)) && (s = (i = o) !== k(i) && E(i) ? { scrollLeft: (a = i).scrollLeft, scrollTop: a.scrollTop } : x(i)), E(o) ? ((m = w(o)).x += o.clientLeft, m.y += o.clientTop) : r && (m.x = O(r))), { x: t.left + s.scrollLeft - m.x, y: t.top + s.scrollTop - m.y, width: t.width, height: t.height } } function M(e) { return { x: e.offsetLeft, y: e.offsetTop, width: e.offsetWidth, height: e.offsetHeight } } function A(e) { return "html" === _(e) ? e : e.assignedSlot || e.parentNode || e.host || z(e) } function L(e) { return ["html", "body", "#document"].indexOf(_(e)) >= 0 ? e.ownerDocument.body : E(e) && S(e) ? e : L(A(e)) } function T(e, o) { void 0 === o && (o = []); var n = L(e), i = "body" === _(n), a = k(n), r = i ? [a].concat(a.visualViewport || [], S(n) ? n : []) : n, t = o.concat(r); return i ? t : t.concat(T(A(r))) } function N(e) { return ["table", "td", "th"].indexOf(_(e)) >= 0 } function F(e) { return E(e) && "fixed" !== I(e).position ? e.offsetParent : null } function B(e) { for (var o = k(e), n = F(e); n && N(n);)n = F(n); return n && "body" === _(n) && "static" === I(n).position ? o : n || o } p.TinyEmitter = b; var D = "top", R = "bottom", q = "right", V = "left", H = [D, R, q, V], U = H.reduce((function (e, o) { return e.concat([o + "-start", o + "-end"]) }), []), W = [].concat(H, ["auto"]).reduce((function (e, o) { return e.concat([o, o + "-start", o + "-end"]) }), []), K = ["beforeRead", "read", "afterRead", "beforeMain", "main", "afterMain", "beforeWrite", "write", "afterWrite"]; function J(e) { var o = new Map, n = new Set, i = []; function a(e) { n.add(e.name), [].concat(e.requires || [], e.requiresIfExists || []).forEach((function (e) { if (!n.has(e)) { var i = o.get(e); i && a(i) } })), i.push(e) } return e.forEach((function (e) { o.set(e.name, e) })), e.forEach((function (e) { n.has(e.name) || a(e) })), i } function G(e) { return e.split("-")[0] } var X = { placement: "bottom", modifiers: [], strategy: "absolute" }; function Y() { for (var e = arguments.length, o = new Array(e), n = 0; n < e; n++)o[n] = arguments[n]; return !o.some((function (e) { return !(e && "function" == typeof e.getBoundingClientRect) })) } function $(e) { void 0 === e && (e = {}); var o = e, n = o.defaultModifiers, i = void 0 === n ? [] : n, a = o.defaultOptions, r = void 0 === a ? X : a; return function (e, o, n) { void 0 === n && (n = r); var a, t, s = { placement: "bottom", orderedModifiers: [], options: Object.assign({}, X, {}, r), modifiersData: {}, elements: { reference: e, popper: o }, attributes: {}, styles: {} }, m = [], c = !1, d = { state: s, setOptions: function (n) { g(), s.options = Object.assign({}, r, {}, s.options, {}, n), s.scrollParents = { reference: C(e) ? T(e) : e.contextElement ? T(e.contextElement) : [], popper: T(o) }; var a, t, c = function (e) { var o = J(e); return K.reduce((function (e, n) { return e.concat(o.filter((function (e) { return e.phase === n }))) }), []) }((a = [].concat(i, s.options.modifiers), t = a.reduce((function (e, o) { var n = e[o.name]; return e[o.name] = n ? Object.assign({}, n, {}, o, { options: Object.assign({}, n.options, {}, o.options), data: Object.assign({}, n.data, {}, o.data) }) : o, e }), {}), Object.keys(t).map((function (e) { return t[e] })))); return s.orderedModifiers = c.filter((function (e) { return e.enabled })), s.orderedModifiers.forEach((function (e) { var o = e.name, n = e.options, i = void 0 === n ? {} : n, a = e.effect; if ("function" == typeof a) { var r = a({ state: s, name: o, instance: d, options: i }), t = function () { }; m.push(r || t) } })), d.update() }, forceUpdate: function () { if (!c) { var e = s.elements, o = e.reference, n = e.popper; if (Y(o, n)) { s.rects = { reference: P(o, B(n), "fixed" === s.options.strategy), popper: M(n) }, s.reset = !1, s.placement = s.options.placement, s.orderedModifiers.forEach((function (e) { return s.modifiersData[e.name] = Object.assign({}, e.data) })); for (var i = 0; i < s.orderedModifiers.length; i++)if (!0 !== s.reset) { var a = s.orderedModifiers[i], r = a.fn, t = a.options, m = void 0 === t ? {} : t, g = a.name; "function" == typeof r && (s = r({ state: s, options: m, name: g, instance: d }) || s) } else s.reset = !1, i = -1 } } }, update: (a = function () { return new Promise((function (e) { d.forceUpdate(), e(s) })) }, function () { return t || (t = new Promise((function (e) { Promise.resolve().then((function () { t = void 0, e(a()) })) }))), t }), destroy: function () { g(), c = !0 } }; if (!Y(e, o)) return d; function g() { m.forEach((function (e) { return e() })), m = [] } return d.setOptions(n).then((function (e) { !c && n.onFirstUpdate && n.onFirstUpdate(e) })), d } } var Z = { passive: !0 }; function Q(e) { return e.split("-")[1] } function ee(e) { return ["top", "bottom"].indexOf(e) >= 0 ? "x" : "y" } function oe(e) { var o, n = e.reference, i = e.element, a = e.placement, r = a ? G(a) : null, t = a ? Q(a) : null, s = n.x + n.width / 2 - i.width / 2, m = n.y + n.height / 2 - i.height / 2; switch (r) { case D: o = { x: s, y: n.y - i.height }; break; case R: o = { x: s, y: n.y + n.height }; break; case q: o = { x: n.x + n.width, y: m }; break; case V: o = { x: n.x - i.width, y: m }; break; default: o = { x: n.x, y: n.y } }var c = r ? ee(r) : null; if (null != c) { var d = "y" === c ? "height" : "width"; switch (t) { case "start": o[c] = Math.floor(o[c]) - Math.floor(n[d] / 2 - i[d] / 2); break; case "end": o[c] = Math.floor(o[c]) + Math.ceil(n[d] / 2 - i[d] / 2) } } return o } var ne = { top: "auto", right: "auto", bottom: "auto", left: "auto" }; function ie(e) { var o, n = e.popper, i = e.popperRect, a = e.placement, r = e.offsets, t = e.position, s = e.gpuAcceleration, m = e.adaptive, c = function (e) { var o = e.x, n = e.y, i = window.devicePixelRatio || 1; return { x: Math.round(o * i) / i || 0, y: Math.round(n * i) / i || 0 } }(r), d = c.x, g = c.y, u = r.hasOwnProperty("x"), l = r.hasOwnProperty("y"), v = V, f = D, y = window; if (m) { var j = B(n); j === k(n) && (j = z(n)), a === D && (f = R, g -= j.clientHeight - i.height, g *= s ? 1 : -1), a === V && (v = q, d -= j.clientWidth - i.width, d *= s ? 1 : -1) } var h, p = Object.assign({ position: t }, m && ne); return s ? Object.assign({}, p, ((h = {})[f] = l ? "0" : "", h[v] = u ? "0" : "", h.transform = (y.devicePixelRatio || 1) < 2 ? "translate(" + d + "px, " + g + "px)" : "translate3d(" + d + "px, " + g + "px, 0)", h)) : Object.assign({}, p, ((o = {})[f] = l ? g + "px" : "", o[v] = u ? d + "px" : "", o.transform = "", o)) } var ae = { left: "right", right: "left", bottom: "top", top: "bottom" }; function re(e) { return e.replace(/left|right|bottom|top/g, (function (e) { return ae[e] })) } var te = { start: "end", end: "start" }; function se(e) { return e.replace(/start|end/g, (function (e) { return te[e] })) } function me(e) { return parseFloat(e) || 0 } function ce(e) { var o = k(e), n = function (e) { var o = E(e) ? I(e) : {}; return { top: me(o.borderTopWidth), right: me(o.borderRightWidth), bottom: me(o.borderBottomWidth), left: me(o.borderLeftWidth) } }(e), i = "html" === _(e), a = O(e), r = e.clientWidth + n.right, t = e.clientHeight + n.bottom; return i && o.innerHeight - e.clientHeight > 50 && (t = o.innerHeight - n.bottom), { top: i ? 0 : e.clientTop, right: e.clientLeft > n.left ? n.right : i ? o.innerWidth - r - a : e.offsetWidth - r, bottom: i ? o.innerHeight - t : e.offsetHeight - t, left: i ? a : e.clientLeft } } function de(e, o) { var n = Boolean(o.getRootNode && o.getRootNode().host); if (e.contains(o)) return !0; if (n) { var i = o; do { if (i && e.isSameNode(i)) return !0; i = i.parentNode || i.host } while (i) } return !1 } function ge(e) { return Object.assign({}, e, { left: e.x, top: e.y, right: e.x + e.width, bottom: e.y + e.height }) } function ue(e, o) { return "viewport" === o ? ge(function (e) { var o = k(e), n = o.visualViewport, i = o.innerWidth, a = o.innerHeight; return n && /iPhone|iPod|iPad/.test(navigator.platform) && (i = n.width, a = n.height), { width: i, height: a, x: 0, y: 0 } }(e)) : E(o) ? w(o) : ge(function (e) { var o = k(e), n = x(e), i = P(z(e), o); return i.height = Math.max(i.height, o.innerHeight), i.width = Math.max(i.width, o.innerWidth), i.x = -n.scrollLeft, i.y = -n.scrollTop, i }(z(e))) } function le(e, o, n) { var i = "clippingParents" === o ? function (e) { var o = T(e), n = ["absolute", "fixed"].indexOf(I(e).position) >= 0 && E(e) ? B(e) : e; return C(n) ? o.filter((function (e) { return C(e) && de(e, n) })) : [] }(e) : [].concat(o), a = [].concat(i, [n]), r = a[0], t = a.reduce((function (o, n) { var i = ue(e, n), a = ce(E(n) ? n : z(e)); return o.top = Math.max(i.top + a.top, o.top), o.right = Math.min(i.right - a.right, o.right), o.bottom = Math.min(i.bottom - a.bottom, o.bottom), o.left = Math.max(i.left + a.left, o.left), o }), ue(e, r)); return t.width = t.right - t.left, t.height = t.bottom - t.top, t.x = t.left, t.y = t.top, t } function ve(e) { return Object.assign({}, { top: 0, right: 0, bottom: 0, left: 0 }, {}, e) } function fe(e, o) { return o.reduce((function (o, n) { return o[n] = e, o }), {}) } function ye(e, o) { void 0 === o && (o = {}); var n = o, i = n.placement, a = void 0 === i ? e.placement : i, r = n.boundary, t = void 0 === r ? "clippingParents" : r, s = n.rootBoundary, m = void 0 === s ? "viewport" : s, c = n.elementContext, d = void 0 === c ? "popper" : c, g = n.altBoundary, u = void 0 !== g && g, l = n.padding, v = void 0 === l ? 0 : l, f = ve("number" != typeof v ? v : fe(v, H)), y = "popper" === d ? "reference" : "popper", j = e.elements.reference, h = e.rects.popper, p = e.elements[u ? y : d], b = le(C(p) ? p : p.contextElement || z(e.elements.popper), t, m), k = w(j), x = oe({ reference: k, element: h, strategy: "absolute", placement: a }), E = ge(Object.assign({}, h, {}, x)), _ = "popper" === d ? E : k, O = { top: b.top - _.top + f.top, bottom: _.bottom - b.bottom + f.bottom, left: b.left - _.left + f.left, right: _.right - b.right + f.right }, I = e.modifiersData.offset; if ("popper" === d && I) { var S = I[a]; Object.keys(O).forEach((function (e) { var o = [q, R].indexOf(e) >= 0 ? 1 : -1, n = [D, R].indexOf(e) >= 0 ? "y" : "x"; O[e] += S[n] * o })) } return O } function je(e, o) { void 0 === o && (o = {}); var n = o, i = n.placement, a = n.boundary, r = n.rootBoundary, t = n.padding, s = n.flipVariations, m = n.allowedAutoPlacements, c = void 0 === m ? W : m, d = Q(i), g = (d ? s ? U : U.filter((function (e) { return Q(e) === d })) : H).filter((function (e) { return c.indexOf(e) >= 0 })).reduce((function (o, n) { return o[n] = ye(e, { placement: n, boundary: a, rootBoundary: r, padding: t })[G(n)], o }), {}); return Object.keys(g).sort((function (e, o) { return g[e] - g[o] })) } function he(e, o, n) { return Math.max(e, Math.min(o, n)) } function pe(e, o, n) { return void 0 === n && (n = { x: 0, y: 0 }), { top: e.top - o.height - n.y, right: e.right - o.width + n.x, bottom: e.bottom - o.height + n.y, left: e.left - o.width - n.x } } function be(e) { return [D, q, R, V].some((function (o) { return e[o] >= 0 })) } var we = $({ defaultModifiers: [{ name: "eventListeners", enabled: !0, phase: "write", fn: function () { }, effect: function (e) { var o = e.state, n = e.instance, i = e.options, a = i.scroll, r = void 0 === a || a, t = i.resize, s = void 0 === t || t, m = k(o.elements.popper), c = [].concat(o.scrollParents.reference, o.scrollParents.popper); return r && c.forEach((function (e) { e.addEventListener("scroll", n.update, Z) })), s && m.addEventListener("resize", n.update, Z), function () { r && c.forEach((function (e) { e.removeEventListener("scroll", n.update, Z) })), s && m.removeEventListener("resize", n.update, Z) } }, data: {} }, { name: "popperOffsets", enabled: !0, phase: "read", fn: function (e) { var o = e.state, n = e.name; o.modifiersData[n] = oe({ reference: o.rects.reference, element: o.rects.popper, strategy: "absolute", placement: o.placement }) }, data: {} }, { name: "computeStyles", enabled: !0, phase: "beforeWrite", fn: function (e) { var o = e.state, n = e.options, i = n.gpuAcceleration, a = void 0 === i || i, r = n.adaptive, t = void 0 === r || r, s = { placement: G(o.placement), popper: o.elements.popper, popperRect: o.rects.popper, gpuAcceleration: a }; null != o.modifiersData.popperOffsets && (o.styles.popper = Object.assign({}, o.styles.popper, {}, ie(Object.assign({}, s, { offsets: o.modifiersData.popperOffsets, position: o.options.strategy, adaptive: t })))), null != o.modifiersData.arrow && (o.styles.arrow = Object.assign({}, o.styles.arrow, {}, ie(Object.assign({}, s, { offsets: o.modifiersData.arrow, position: "absolute", adaptive: !1 })))), o.attributes.popper = Object.assign({}, o.attributes.popper, { "data-popper-placement": o.placement }) }, data: {} }, { name: "applyStyles", enabled: !0, phase: "write", fn: function (e) { var o = e.state; Object.keys(o.elements).forEach((function (e) { var n = o.styles[e] || {}, i = o.attributes[e] || {}, a = o.elements[e]; E(a) && _(a) && (Object.assign(a.style, n), Object.keys(i).forEach((function (e) { var o = i[e]; !1 === o ? a.removeAttribute(e) : a.setAttribute(e, !0 === o ? "" : o) }))) })) }, effect: function (e) { var o = e.state, n = { popper: { position: o.options.strategy, left: "0", top: "0", margin: "0" }, arrow: { position: "absolute" }, reference: {} }; return Object.assign(o.elements.popper.style, n.popper), o.elements.arrow && Object.assign(o.elements.arrow.style, n.arrow), function () { Object.keys(o.elements).forEach((function (e) { var i = o.elements[e], a = o.attributes[e] || {}, r = Object.keys(o.styles.hasOwnProperty(e) ? o.styles[e] : n[e]).reduce((function (e, o) { return e[o] = "", e }), {}); E(i) && _(i) && (Object.assign(i.style, r), Object.keys(a).forEach((function (e) { i.removeAttribute(e) }))) })) } }, requires: ["computeStyles"] }, { name: "offset", enabled: !0, phase: "main", requires: ["popperOffsets"], fn: function (e) { var o = e.state, n = e.options, i = e.name, a = n.offset, r = void 0 === a ? [0, 0] : a, t = W.reduce((function (e, n) { return e[n] = function (e, o, n) { var i = G(e), a = [V, D].indexOf(i) >= 0 ? -1 : 1, r = "function" == typeof n ? n(Object.assign({}, o, { placement: e })) : n, t = r[0], s = r[1]; return t = t || 0, s = (s || 0) * a, [V, q].indexOf(i) >= 0 ? { x: s, y: t } : { x: t, y: s } }(n, o.rects, r), e }), {}), s = t[o.placement], m = s.x, c = s.y; null != o.modifiersData.popperOffsets && (o.modifiersData.popperOffsets.x += m, o.modifiersData.popperOffsets.y += c), o.modifiersData[i] = t } }, { name: "flip", enabled: !0, phase: "main", fn: function (e) { var o = e.state, n = e.options, i = e.name; if (!o.modifiersData[i]._skip) { for (var a = n.mainAxis, r = void 0 === a || a, t = n.altAxis, s = void 0 === t || t, m = n.fallbackPlacements, c = n.padding, d = n.boundary, g = n.rootBoundary, u = n.altBoundary, l = n.flipVariations, v = void 0 === l || l, f = n.allowedAutoPlacements, y = o.options.placement, j = G(y), h = m || (j === y || !v ? [re(y)] : function (e) { if ("auto" === G(e)) return []; var o = re(e); return [se(e), o, se(o)] }(y)), p = [y].concat(h).reduce((function (e, n) { return e.concat("auto" === G(n) ? je(o, { placement: n, boundary: d, rootBoundary: g, padding: c, flipVariations: v, allowedAutoPlacements: f }) : n) }), []), b = o.rects.reference, w = o.rects.popper, k = new Map, x = !0, C = p[0], E = 0; E < p.length; E++) { var _ = p[E], z = G(_), O = "start" === Q(_), I = [D, R].indexOf(z) >= 0, S = I ? "width" : "height", P = ye(o, { placement: _, boundary: d, rootBoundary: g, altBoundary: u, padding: c }), M = I ? O ? q : V : O ? R : D; b[S] > w[S] && (M = re(M)); var A = re(M), L = []; if (r && L.push(P[z] <= 0), s && L.push(P[M] <= 0, P[A] <= 0), L.every((function (e) { return e }))) { C = _, x = !1; break } k.set(_, L) } if (x) for (var T = function (e) { var o = p.find((function (o) { var n = k.get(o); if (n) return n.slice(0, e).every((function (e) { return e })) })); if (o) return C = o, "break" }, N = v ? 3 : 1; N > 0; N--) { if ("break" === T(N)) break } o.placement !== C && (o.modifiersData[i]._skip = !0, o.placement = C, o.reset = !0) } }, requiresIfExists: ["offset"], data: { _skip: !1 } }, { name: "preventOverflow", enabled: !0, phase: "main", fn: function (e) { var o = e.state, n = e.options, i = e.name, a = n.mainAxis, r = void 0 === a || a, t = n.altAxis, s = void 0 !== t && t, m = n.boundary, c = n.rootBoundary, d = n.altBoundary, g = n.padding, u = n.tether, l = void 0 === u || u, v = n.tetherOffset, f = void 0 === v ? 0 : v, y = ye(o, { boundary: m, rootBoundary: c, padding: g, altBoundary: d }), j = G(o.placement), h = Q(o.placement), p = !h, b = ee(j), w = "x" === b ? "y" : "x", k = o.modifiersData.popperOffsets, x = o.rects.reference, C = o.rects.popper, E = "function" == typeof f ? f(Object.assign({}, o.rects, { placement: o.placement })) : f, _ = { x: 0, y: 0 }; if (k) { if (r) { var z = "y" === b ? D : V, O = "y" === b ? R : q, I = "y" === b ? "height" : "width", S = k[b], P = k[b] + y[z], A = k[b] - y[O], L = l ? -C[I] / 2 : 0, T = "start" === h ? x[I] : C[I], N = "start" === h ? -C[I] : -x[I], F = o.elements.arrow, H = l && F ? M(F) : { width: 0, height: 0 }, U = o.modifiersData["arrow#persistent"] ? o.modifiersData["arrow#persistent"].padding : { top: 0, right: 0, bottom: 0, left: 0 }, W = U[z], K = U[O], J = he(0, x[I], H[I]), X = p ? x[I] / 2 - L - J - W - E : T - J - W - E, Y = p ? -x[I] / 2 + L + J + K + E : N + J + K + E, $ = o.elements.arrow && B(o.elements.arrow), Z = $ ? "y" === b ? $.clientTop || 0 : $.clientLeft || 0 : 0, oe = o.modifiersData.offset ? o.modifiersData.offset[o.placement][b] : 0, ne = k[b] + X - oe - Z, ie = k[b] + Y - oe, ae = he(l ? Math.min(P, ne) : P, S, l ? Math.max(A, ie) : A); k[b] = ae, _[b] = ae - S } if (s) { var re = "x" === b ? D : V, te = "x" === b ? R : q, se = k[w], me = he(se + y[re], se, se - y[te]); k[w] = me, _[w] = me - se } o.modifiersData[i] = _ } }, requiresIfExists: ["offset"] }, { name: "arrow", enabled: !0, phase: "main", fn: function (e) { var o, n = e.state, i = e.name, a = n.elements.arrow, r = n.modifiersData.popperOffsets, t = G(n.placement), s = ee(t), m = [V, q].indexOf(t) >= 0 ? "height" : "width"; if (a && r) { var c = n.modifiersData[i + "#persistent"].padding, d = M(a), g = "y" === s ? D : V, u = "y" === s ? R : q, l = n.rects.reference[m] + n.rects.reference[s] - r[s] - n.rects.popper[m], v = r[s] - n.rects.reference[s], f = B(a), y = f ? "y" === s ? f.clientHeight || 0 : f.clientWidth || 0 : 0, j = l / 2 - v / 2, h = c[g], p = y - d[m] - c[u], b = y / 2 - d[m] / 2 + j, w = he(h, b, p), k = s; n.modifiersData[i] = ((o = {})[k] = w, o.centerOffset = w - b, o) } }, effect: function (e) { var o = e.state, n = e.options, i = e.name, a = n.element, r = void 0 === a ? "[data-popper-arrow]" : a, t = n.padding, s = void 0 === t ? 0 : t; null != r && ("string" != typeof r || (r = o.elements.popper.querySelector(r))) && de(o.elements.popper, r) && (o.elements.arrow = r, o.modifiersData[i + "#persistent"] = { padding: ve("number" != typeof s ? s : fe(s, H)) }) }, requires: ["popperOffsets"], requiresIfExists: ["preventOverflow"] }, { name: "hide", enabled: !0, phase: "main", requiresIfExists: ["preventOverflow"], fn: function (e) { var o = e.state, n = e.name, i = o.rects.reference, a = o.rects.popper, r = o.modifiersData.preventOverflow, t = ye(o, { elementContext: "reference" }), s = ye(o, { altBoundary: !0 }), m = pe(t, i), c = pe(s, a, r), d = be(m), g = be(c); o.modifiersData[n] = { referenceClippingOffsets: m, popperEscapeOffsets: c, isReferenceHidden: d, hasPopperEscaped: g }, o.attributes.popper = Object.assign({}, o.attributes.popper, { "data-popper-reference-hidden": d, "data-popper-escaped": g }) } }] }), ke = function () { var e = { base: "https://twemoji.maxcdn.com/v/13.0.0/", ext: ".png", size: "72x72", className: "emoji", convert: { fromCodePoint: function (e) { var o = "string" == typeof e ? parseInt(e, 16) : e; if (o < 65536) return s(o); return s(55296 + ((o -= 65536) >> 10), 56320 + (1023 & o)) }, toCodePoint: j }, onerror: function () { this.parentNode && this.parentNode.replaceChild(m(this.alt, !1), this) }, parse: function (o, n) { n && "function" != typeof n || (n = { callback: n }); return ("string" == typeof o ? l : u)(o, { callback: n.callback || c, attributes: "function" == typeof n.attributes ? n.attributes : f, base: "string" == typeof n.base ? n.base : e.base, ext: n.ext || e.ext, size: n.folder || (i = n.size || e.size, "number" == typeof i ? i + "x" + i : i), className: n.className || e.className, onerror: n.onerror || e.onerror }); var i }, replace: y, test: function (e) { n.lastIndex = 0; var o = n.test(e); return n.lastIndex = 0, o } }, o = { "&": "&", "<": "<", ">": ">", "'": "'", '"': """ }, n = /(?:\ud83d\udc68\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffc-\udfff]|\ud83d\udc68\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffd-\udfff]|\ud83d\udc68\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffc\udffe\udfff]|\ud83d\udc68\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffd\udfff]|\ud83d\udc68\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffe]|\ud83d\udc69\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffc-\udfff]|\ud83d\udc69\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffc-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffd-\udfff]|\ud83d\udc69\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb\udffd-\udfff]|\ud83d\udc69\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb\udffc\udffe\udfff]|\ud83d\udc69\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb\udffc\udffe\udfff]|\ud83d\udc69\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffd\udfff]|\ud83d\udc69\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb-\udffd\udfff]|\ud83d\udc69\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83d\udc68\ud83c[\udffb-\udffe]|\ud83d\udc69\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83d\udc69\ud83c[\udffb-\udffe]|\ud83e\uddd1\ud83c\udffb\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udffc\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udffd\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udffe\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\ud83c\udfff\u200d\ud83e\udd1d\u200d\ud83e\uddd1\ud83c[\udffb-\udfff]|\ud83e\uddd1\u200d\ud83e\udd1d\u200d\ud83e\uddd1|\ud83d\udc6b\ud83c[\udffb-\udfff]|\ud83d\udc6c\ud83c[\udffb-\udfff]|\ud83d\udc6d\ud83c[\udffb-\udfff]|\ud83d[\udc6b-\udc6d])|(?:\ud83d[\udc68\udc69]|\ud83e\uddd1)(?:\ud83c[\udffb-\udfff])?\u200d(?:\u2695\ufe0f|\u2696\ufe0f|\u2708\ufe0f|\ud83c[\udf3e\udf73\udf7c\udf84\udf93\udfa4\udfa8\udfeb\udfed]|\ud83d[\udcbb\udcbc\udd27\udd2c\ude80\ude92]|\ud83e[\uddaf-\uddb3\uddbc\uddbd])|(?:\ud83c[\udfcb\udfcc]|\ud83d[\udd74\udd75]|\u26f9)((?:\ud83c[\udffb-\udfff]|\ufe0f)\u200d[\u2640\u2642]\ufe0f)|(?:\ud83c[\udfc3\udfc4\udfca]|\ud83d[\udc6e\udc70\udc71\udc73\udc77\udc81\udc82\udc86\udc87\ude45-\ude47\ude4b\ude4d\ude4e\udea3\udeb4-\udeb6]|\ud83e[\udd26\udd35\udd37-\udd39\udd3d\udd3e\uddb8\uddb9\uddcd-\uddcf\uddd6-\udddd])(?:\ud83c[\udffb-\udfff])?\u200d[\u2640\u2642]\ufe0f|(?:\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68|\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d[\udc68\udc69]|\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc68|\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d[\udc66\udc67]|\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d[\udc68\udc69]|\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66|\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d[\udc66\udc67]|\ud83c\udff3\ufe0f\u200d\u26a7\ufe0f|\ud83c\udff3\ufe0f\u200d\ud83c\udf08|\ud83c\udff4\u200d\u2620\ufe0f|\ud83d\udc15\u200d\ud83e\uddba|\ud83d\udc3b\u200d\u2744\ufe0f|\ud83d\udc41\u200d\ud83d\udde8|\ud83d\udc68\u200d\ud83d[\udc66\udc67]|\ud83d\udc69\u200d\ud83d[\udc66\udc67]|\ud83d\udc6f\u200d\u2640\ufe0f|\ud83d\udc6f\u200d\u2642\ufe0f|\ud83e\udd3c\u200d\u2640\ufe0f|\ud83e\udd3c\u200d\u2642\ufe0f|\ud83e\uddde\u200d\u2640\ufe0f|\ud83e\uddde\u200d\u2642\ufe0f|\ud83e\udddf\u200d\u2640\ufe0f|\ud83e\udddf\u200d\u2642\ufe0f|\ud83d\udc08\u200d\u2b1b)|[#*0-9]\ufe0f?\u20e3|(?:[©®\u2122\u265f]\ufe0f)|(?:\ud83c[\udc04\udd70\udd71\udd7e\udd7f\ude02\ude1a\ude2f\ude37\udf21\udf24-\udf2c\udf36\udf7d\udf96\udf97\udf99-\udf9b\udf9e\udf9f\udfcd\udfce\udfd4-\udfdf\udff3\udff5\udff7]|\ud83d[\udc3f\udc41\udcfd\udd49\udd4a\udd6f\udd70\udd73\udd76-\udd79\udd87\udd8a-\udd8d\udda5\udda8\uddb1\uddb2\uddbc\uddc2-\uddc4\uddd1-\uddd3\udddc-\uddde\udde1\udde3\udde8\uddef\uddf3\uddfa\udecb\udecd-\udecf\udee0-\udee5\udee9\udef0\udef3]|[\u203c\u2049\u2139\u2194-\u2199\u21a9\u21aa\u231a\u231b\u2328\u23cf\u23ed-\u23ef\u23f1\u23f2\u23f8-\u23fa\u24c2\u25aa\u25ab\u25b6\u25c0\u25fb-\u25fe\u2600-\u2604\u260e\u2611\u2614\u2615\u2618\u2620\u2622\u2623\u2626\u262a\u262e\u262f\u2638-\u263a\u2640\u2642\u2648-\u2653\u2660\u2663\u2665\u2666\u2668\u267b\u267f\u2692-\u2697\u2699\u269b\u269c\u26a0\u26a1\u26a7\u26aa\u26ab\u26b0\u26b1\u26bd\u26be\u26c4\u26c5\u26c8\u26cf\u26d1\u26d3\u26d4\u26e9\u26ea\u26f0-\u26f5\u26f8\u26fa\u26fd\u2702\u2708\u2709\u270f\u2712\u2714\u2716\u271d\u2721\u2733\u2734\u2744\u2747\u2757\u2763\u2764\u27a1\u2934\u2935\u2b05-\u2b07\u2b1b\u2b1c\u2b50\u2b55\u3030\u303d\u3297\u3299])(?:\ufe0f|(?!\ufe0e))|(?:(?:\ud83c[\udfcb\udfcc]|\ud83d[\udd74\udd75\udd90]|[\u261d\u26f7\u26f9\u270c\u270d])(?:\ufe0f|(?!\ufe0e))|(?:\ud83c[\udf85\udfc2-\udfc4\udfc7\udfca]|\ud83d[\udc42\udc43\udc46-\udc50\udc66-\udc69\udc6e\udc70-\udc78\udc7c\udc81-\udc83\udc85-\udc87\udcaa\udd7a\udd95\udd96\ude45-\ude47\ude4b-\ude4f\udea3\udeb4-\udeb6\udec0\udecc]|\ud83e[\udd0c\udd0f\udd18-\udd1c\udd1e\udd1f\udd26\udd30-\udd39\udd3d\udd3e\udd77\uddb5\uddb6\uddb8\uddb9\uddbb\uddcd-\uddcf\uddd1-\udddd]|[\u270a\u270b]))(?:\ud83c[\udffb-\udfff])?|(?:\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f|\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc73\udb40\udc63\udb40\udc74\udb40\udc7f|\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f|\ud83c\udde6\ud83c[\udde8-\uddec\uddee\uddf1\uddf2\uddf4\uddf6-\uddfa\uddfc\uddfd\uddff]|\ud83c\udde7\ud83c[\udde6\udde7\udde9-\uddef\uddf1-\uddf4\uddf6-\uddf9\uddfb\uddfc\uddfe\uddff]|\ud83c\udde8\ud83c[\udde6\udde8\udde9\uddeb-\uddee\uddf0-\uddf5\uddf7\uddfa-\uddff]|\ud83c\udde9\ud83c[\uddea\uddec\uddef\uddf0\uddf2\uddf4\uddff]|\ud83c\uddea\ud83c[\udde6\udde8\uddea\uddec\udded\uddf7-\uddfa]|\ud83c\uddeb\ud83c[\uddee-\uddf0\uddf2\uddf4\uddf7]|\ud83c\uddec\ud83c[\udde6\udde7\udde9-\uddee\uddf1-\uddf3\uddf5-\uddfa\uddfc\uddfe]|\ud83c\udded\ud83c[\uddf0\uddf2\uddf3\uddf7\uddf9\uddfa]|\ud83c\uddee\ud83c[\udde8-\uddea\uddf1-\uddf4\uddf6-\uddf9]|\ud83c\uddef\ud83c[\uddea\uddf2\uddf4\uddf5]|\ud83c\uddf0\ud83c[\uddea\uddec-\uddee\uddf2\uddf3\uddf5\uddf7\uddfc\uddfe\uddff]|\ud83c\uddf1\ud83c[\udde6-\udde8\uddee\uddf0\uddf7-\uddfb\uddfe]|\ud83c\uddf2\ud83c[\udde6\udde8-\udded\uddf0-\uddff]|\ud83c\uddf3\ud83c[\udde6\udde8\uddea-\uddec\uddee\uddf1\uddf4\uddf5\uddf7\uddfa\uddff]|\ud83c\uddf4\ud83c\uddf2|\ud83c\uddf5\ud83c[\udde6\uddea-\udded\uddf0-\uddf3\uddf7-\uddf9\uddfc\uddfe]|\ud83c\uddf6\ud83c\udde6|\ud83c\uddf7\ud83c[\uddea\uddf4\uddf8\uddfa\uddfc]|\ud83c\uddf8\ud83c[\udde6-\uddea\uddec-\uddf4\uddf7-\uddf9\uddfb\uddfd-\uddff]|\ud83c\uddf9\ud83c[\udde6\udde8\udde9\uddeb-\udded\uddef-\uddf4\uddf7\uddf9\uddfb\uddfc\uddff]|\ud83c\uddfa\ud83c[\udde6\uddec\uddf2\uddf3\uddf8\uddfe\uddff]|\ud83c\uddfb\ud83c[\udde6\udde8\uddea\uddec\uddee\uddf3\uddfa]|\ud83c\uddfc\ud83c[\uddeb\uddf8]|\ud83c\uddfd\ud83c\uddf0|\ud83c\uddfe\ud83c[\uddea\uddf9]|\ud83c\uddff\ud83c[\udde6\uddf2\uddfc]|\ud83c[\udccf\udd8e\udd91-\udd9a\udde6-\uddff\ude01\ude32-\ude36\ude38-\ude3a\ude50\ude51\udf00-\udf20\udf2d-\udf35\udf37-\udf7c\udf7e-\udf84\udf86-\udf93\udfa0-\udfc1\udfc5\udfc6\udfc8\udfc9\udfcf-\udfd3\udfe0-\udff0\udff4\udff8-\udfff]|\ud83d[\udc00-\udc3e\udc40\udc44\udc45\udc51-\udc65\udc6a\udc6f\udc79-\udc7b\udc7d-\udc80\udc84\udc88-\udca9\udcab-\udcfc\udcff-\udd3d\udd4b-\udd4e\udd50-\udd67\udda4\uddfb-\ude44\ude48-\ude4a\ude80-\udea2\udea4-\udeb3\udeb7-\udebf\udec1-\udec5\uded0-\uded2\uded5-\uded7\udeeb\udeec\udef4-\udefc\udfe0-\udfeb]|\ud83e[\udd0d\udd0e\udd10-\udd17\udd1d\udd20-\udd25\udd27-\udd2f\udd3a\udd3c\udd3f-\udd45\udd47-\udd76\udd78\udd7a-\uddb4\uddb7\uddba\uddbc-\uddcb\uddd0\uddde-\uddff\ude70-\ude74\ude78-\ude7a\ude80-\ude86\ude90-\udea8\udeb0-\udeb6\udec0-\udec2\uded0-\uded6]|[\u23e9-\u23ec\u23f0\u23f3\u267e\u26ce\u2705\u2728\u274c\u274e\u2753-\u2755\u2795-\u2797\u27b0\u27bf\ue50a])|\ufe0f/g, i = /\uFE0F/g, a = String.fromCharCode(8205), r = /[&<>'"]/g, t = /^(?:iframe|noframes|noscript|script|select|style|textarea)$/, s = String.fromCharCode; return e; function m(e, o) { return document.createTextNode(o ? e.replace(i, "") : e) } function c(e, o) { return "".concat(o.base, o.size, "/", e, o.ext) } function d(e, o) { for (var n, i, a = e.childNodes, r = a.length; r--;)3 === (i = (n = a[r]).nodeType) ? o.push(n) : 1 !== i || "ownerSVGElement" in n || t.test(n.nodeName.toLowerCase()) || d(n, o); return o } function g(e) { return j(e.indexOf(a) < 0 ? e.replace(i, "") : e) } function u(e, o) { for (var i, a, r, t, s, c, u, l, v, f, y, j, h, p = d(e, []), b = p.length; b--;) { for (r = !1, t = document.createDocumentFragment(), c = (s = p[b]).nodeValue, l = 0; u = n.exec(c);) { if ((v = u.index) !== l && t.appendChild(m(c.slice(l, v), !0)), j = g(y = u[0]), l = v + y.length, h = o.callback(j, o), j && h) { for (a in (f = new Image).onerror = o.onerror, f.setAttribute("draggable", "false"), i = o.attributes(y, j)) i.hasOwnProperty(a) && 0 !== a.indexOf("on") && !f.hasAttribute(a) && f.setAttribute(a, i[a]); f.className = o.className, f.alt = y, f.src = h, r = !0, t.appendChild(f) } f || t.appendChild(m(y, !1)), f = null } r && (l < c.length && t.appendChild(m(c.slice(l), !0)), s.parentNode.replaceChild(t, s)) } return e } function l(e, o) { return y(e, (function (e) { var n, i, a = e, t = g(e), s = o.callback(t, o); if (t && s) { for (i in a = "<img ".concat('class="', o.className, '" ', 'draggable="false" ', 'alt="', e, '"', ' src="', s, '"'), n = o.attributes(e, t)) n.hasOwnProperty(i) && 0 !== i.indexOf("on") && -1 === a.indexOf(" " + i + "=") && (a = a.concat(" ", i, '="', n[i].replace(r, v), '"')); a = a.concat("/>") } return a })) } function v(e) { return o[e] } function f() { return null } function y(e, o) { return String(e).replace(n, o) } function j(e, o) { for (var n = [], i = 0, a = 0, r = 0; r < e.length;)i = e.charCodeAt(r++), a ? (n.push((65536 + (a - 55296 << 10) + (i - 56320)).toString(16)), a = 0) : 55296 <= i && i <= 56319 ? a = i : n.push(i.toString(16)); return n.join(o || "-") } }(), xe = { categories: ["smileys", "people", "animals", "food", "travel", "activities", "objects", "symbols", "flags"], emoji: [{ emoji: "😀", category: 0, name: "grinning face", version: "1.0" }, { emoji: "😃", category: 0, name: "grinning face with big eyes", version: "1.0" }, { emoji: "😄", category: 0, name: "grinning face with smiling eyes", version: "1.0" }, { emoji: "ðŸ˜", category: 0, name: "beaming face with smiling eyes", version: "1.0" }, { emoji: "😆", category: 0, name: "grinning squinting face", version: "1.0" }, { emoji: "😅", category: 0, name: "grinning face with sweat", version: "1.0" }, { emoji: "🤣", category: 0, name: "rolling on the floor laughing", version: "3.0" }, { emoji: "😂", category: 0, name: "face with tears of joy", version: "1.0" }, { emoji: "🙂", category: 0, name: "slightly smiling face", version: "1.0" }, { emoji: "🙃", category: 0, name: "upside-down face", version: "1.0" }, { emoji: "😉", category: 0, name: "winking face", version: "1.0" }, { emoji: "😊", category: 0, name: "smiling face with smiling eyes", version: "1.0" }, { emoji: "😇", category: 0, name: "smiling face with halo", version: "1.0" }, { emoji: "🥰", category: 0, name: "smiling face with hearts", version: "11.0" }, { emoji: "ðŸ˜", category: 0, name: "smiling face with heart-eyes", version: "1.0" }, { emoji: "🤩", category: 0, name: "star-struck", version: "5.0" }, { emoji: "😘", category: 0, name: "face blowing a kiss", version: "1.0" }, { emoji: "😗", category: 0, name: "kissing face", version: "1.0" }, { emoji: "☺ï¸", category: 0, name: "smiling face", version: "1.0" }, { emoji: "😚", category: 0, name: "kissing face with closed eyes", version: "1.0" }, { emoji: "😙", category: 0, name: "kissing face with smiling eyes", version: "1.0" }, { emoji: "🥲", category: 0, name: "smiling face with tear", version: "13.0" }, { emoji: "😋", category: 0, name: "face savoring food", version: "1.0" }, { emoji: "😛", category: 0, name: "face with tongue", version: "1.0" }, { emoji: "😜", category: 0, name: "winking face with tongue", version: "1.0" }, { emoji: "🤪", category: 0, name: "zany face", version: "5.0" }, { emoji: "ðŸ˜", category: 0, name: "squinting face with tongue", version: "1.0" }, { emoji: "🤑", category: 0, name: "money-mouth face", version: "1.0" }, { emoji: "🤗", category: 0, name: "hugging face", version: "1.0" }, { emoji: "ðŸ¤", category: 0, name: "face with hand over mouth", version: "5.0" }, { emoji: "🤫", category: 0, name: "shushing face", version: "5.0" }, { emoji: "🤔", category: 0, name: "thinking face", version: "1.0" }, { emoji: "ðŸ¤", category: 0, name: "zipper-mouth face", version: "1.0" }, { emoji: "🤨", category: 0, name: "face with raised eyebrow", version: "5.0" }, { emoji: "ðŸ˜", category: 0, name: "neutral face", version: "1.0" }, { emoji: "😑", category: 0, name: "expressionless face", version: "1.0" }, { emoji: "😶", category: 0, name: "face without mouth", version: "1.0" }, { emoji: "ðŸ˜", category: 0, name: "smirking face", version: "1.0" }, { emoji: "😒", category: 0, name: "unamused face", version: "1.0" }, { emoji: "🙄", category: 0, name: "face with rolling eyes", version: "1.0" }, { emoji: "😬", category: 0, name: "grimacing face", version: "1.0" }, { emoji: "🤥", category: 0, name: "lying face", version: "3.0" }, { emoji: "😌", category: 0, name: "relieved face", version: "1.0" }, { emoji: "😔", category: 0, name: "pensive face", version: "1.0" }, { emoji: "😪", category: 0, name: "sleepy face", version: "1.0" }, { emoji: "🤤", category: 0, name: "drooling face", version: "3.0" }, { emoji: "😴", category: 0, name: "sleeping face", version: "1.0" }, { emoji: "😷", category: 0, name: "face with medical mask", version: "1.0" }, { emoji: "🤒", category: 0, name: "face with thermometer", version: "1.0" }, { emoji: "🤕", category: 0, name: "face with head-bandage", version: "1.0" }, { emoji: "🤢", category: 0, name: "nauseated face", version: "3.0" }, { emoji: "🤮", category: 0, name: "face vomiting", version: "5.0" }, { emoji: "🤧", category: 0, name: "sneezing face", version: "3.0" }, { emoji: "🥵", category: 0, name: "hot face", version: "11.0" }, { emoji: "🥶", category: 0, name: "cold face", version: "11.0" }, { emoji: "🥴", category: 0, name: "woozy face", version: "11.0" }, { emoji: "😵", category: 0, name: "dizzy face", version: "1.0" }, { emoji: "🤯", category: 0, name: "exploding head", version: "5.0" }, { emoji: "🤠", category: 0, name: "cowboy hat face", version: "3.0" }, { emoji: "🥳", category: 0, name: "partying face", version: "11.0" }, { emoji: "🥸", category: 0, name: "disguised face", version: "13.0" }, { emoji: "😎", category: 0, name: "smiling face with sunglasses", version: "1.0" }, { emoji: "🤓", category: 0, name: "nerd face", version: "1.0" }, { emoji: "ðŸ§", category: 0, name: "face with monocle", version: "5.0" }, { emoji: "😕", category: 0, name: "confused face", version: "1.0" }, { emoji: "😟", category: 0, name: "worried face", version: "1.0" }, { emoji: "ðŸ™", category: 0, name: "slightly frowning face", version: "1.0" }, { emoji: "☹ï¸", category: 0, name: "frowning face", version: "1.0" }, { emoji: "😮", category: 0, name: "face with open mouth", version: "1.0" }, { emoji: "😯", category: 0, name: "hushed face", version: "1.0" }, { emoji: "😲", category: 0, name: "astonished face", version: "1.0" }, { emoji: "😳", category: 0, name: "flushed face", version: "1.0" }, { emoji: "🥺", category: 0, name: "pleading face", version: "11.0" }, { emoji: "😦", category: 0, name: "frowning face with open mouth", version: "1.0" }, { emoji: "😧", category: 0, name: "anguished face", version: "1.0" }, { emoji: "😨", category: 0, name: "fearful face", version: "1.0" }, { emoji: "😰", category: 0, name: "anxious face with sweat", version: "1.0" }, { emoji: "😥", category: 0, name: "sad but relieved face", version: "1.0" }, { emoji: "😢", category: 0, name: "crying face", version: "1.0" }, { emoji: "ðŸ˜", category: 0, name: "loudly crying face", version: "1.0" }, { emoji: "😱", category: 0, name: "face screaming in fear", version: "1.0" }, { emoji: "😖", category: 0, name: "confounded face", version: "1.0" }, { emoji: "😣", category: 0, name: "persevering face", version: "1.0" }, { emoji: "😞", category: 0, name: "disappointed face", version: "1.0" }, { emoji: "😓", category: 0, name: "downcast face with sweat", version: "1.0" }, { emoji: "😩", category: 0, name: "weary face", version: "1.0" }, { emoji: "😫", category: 0, name: "tired face", version: "1.0" }, { emoji: "🥱", category: 0, name: "yawning face", version: "12.0" }, { emoji: "😤", category: 0, name: "face with steam from nose", version: "1.0" }, { emoji: "😡", category: 0, name: "pouting face", version: "1.0" }, { emoji: "😠", category: 0, name: "angry face", version: "1.0" }, { emoji: "🤬", category: 0, name: "face with symbols on mouth", version: "5.0" }, { emoji: "😈", category: 0, name: "smiling face with horns", version: "1.0" }, { emoji: "👿", category: 0, name: "angry face with horns", version: "1.0" }, { emoji: "💀", category: 0, name: "skull", version: "1.0" }, { emoji: "☠ï¸", category: 0, name: "skull and crossbones", version: "1.0" }, { emoji: "💩", category: 0, name: "pile of poo", version: "1.0" }, { emoji: "🤡", category: 0, name: "clown face", version: "3.0" }, { emoji: "👹", category: 0, name: "ogre", version: "1.0" }, { emoji: "👺", category: 0, name: "goblin", version: "1.0" }, { emoji: "👻", category: 0, name: "ghost", version: "1.0" }, { emoji: "👽", category: 0, name: "alien", version: "1.0" }, { emoji: "👾", category: 0, name: "alien monster", version: "1.0" }, { emoji: "🤖", category: 0, name: "robot", version: "1.0" }, { emoji: "😺", category: 0, name: "grinning cat", version: "1.0" }, { emoji: "😸", category: 0, name: "grinning cat with smiling eyes", version: "1.0" }, { emoji: "😹", category: 0, name: "cat with tears of joy", version: "1.0" }, { emoji: "😻", category: 0, name: "smiling cat with heart-eyes", version: "1.0" }, { emoji: "😼", category: 0, name: "cat with wry smile", version: "1.0" }, { emoji: "😽", category: 0, name: "kissing cat", version: "1.0" }, { emoji: "🙀", category: 0, name: "weary cat", version: "1.0" }, { emoji: "😿", category: 0, name: "crying cat", version: "1.0" }, { emoji: "😾", category: 0, name: "pouting cat", version: "1.0" }, { emoji: "🙈", category: 0, name: "see-no-evil monkey", version: "1.0" }, { emoji: "🙉", category: 0, name: "hear-no-evil monkey", version: "1.0" }, { emoji: "🙊", category: 0, name: "speak-no-evil monkey", version: "1.0" }, { emoji: "💋", category: 0, name: "kiss mark", version: "1.0" }, { emoji: "💌", category: 0, name: "love letter", version: "1.0" }, { emoji: "💘", category: 0, name: "heart with arrow", version: "1.0" }, { emoji: "ðŸ’", category: 0, name: "heart with ribbon", version: "1.0" }, { emoji: "💖", category: 0, name: "sparkling heart", version: "1.0" }, { emoji: "💗", category: 0, name: "growing heart", version: "1.0" }, { emoji: "💓", category: 0, name: "beating heart", version: "1.0" }, { emoji: "💞", category: 0, name: "revolving hearts", version: "1.0" }, { emoji: "💕", category: 0, name: "two hearts", version: "1.0" }, { emoji: "💟", category: 0, name: "heart decoration", version: "1.0" }, { emoji: "â£ï¸", category: 0, name: "heart exclamation", version: "1.0" }, { emoji: "💔", category: 0, name: "broken heart", version: "1.0" }, { emoji: "â¤ï¸", category: 0, name: "red heart", version: "1.0" }, { emoji: "🧡", category: 0, name: "orange heart", version: "5.0" }, { emoji: "💛", category: 0, name: "yellow heart", version: "1.0" }, { emoji: "💚", category: 0, name: "green heart", version: "1.0" }, { emoji: "💙", category: 0, name: "blue heart", version: "1.0" }, { emoji: "💜", category: 0, name: "purple heart", version: "1.0" }, { emoji: "🤎", category: 0, name: "brown heart", version: "12.0" }, { emoji: "🖤", category: 0, name: "black heart", version: "3.0" }, { emoji: "ðŸ¤", category: 0, name: "white heart", version: "12.0" }, { emoji: "💯", category: 0, name: "hundred points", version: "1.0" }, { emoji: "💢", category: 0, name: "anger symbol", version: "1.0" }, { emoji: "💥", category: 0, name: "collision", version: "1.0" }, { emoji: "💫", category: 0, name: "dizzy", version: "1.0" }, { emoji: "💦", category: 0, name: "sweat droplets", version: "1.0" }, { emoji: "💨", category: 0, name: "dashing away", version: "1.0" }, { emoji: "🕳ï¸", category: 0, name: "hole", version: "1.0" }, { emoji: "💣", category: 0, name: "bomb", version: "1.0" }, { emoji: "💬", category: 0, name: "speech balloon", version: "1.0" }, { emoji: "ðŸ‘ï¸â€ðŸ—¨ï¸", category: 0, name: "eye in speech bubble", version: "2.0" }, { emoji: "🗨ï¸", category: 0, name: "left speech bubble", version: "2.0" }, { emoji: "🗯ï¸", category: 0, name: "right anger bubble", version: "1.0" }, { emoji: "ðŸ’", category: 0, name: "thought balloon", version: "1.0" }, { emoji: "💤", category: 0, name: "zzz", version: "1.0" }, { emoji: "👋", category: 1, name: "waving hand", variations: ["👋ðŸ»", "👋ðŸ¼", "👋ðŸ½", "👋ðŸ¾", "👋ðŸ¿"], version: "1.0" }, { emoji: "🤚", category: 1, name: "raised back of hand", variations: ["🤚ðŸ»", "🤚ðŸ¼", "🤚ðŸ½", "🤚ðŸ¾", "🤚ðŸ¿"], version: "3.0" }, { emoji: "ðŸ–ï¸", category: 1, name: "hand with fingers splayed", variations: ["ðŸ–ðŸ»", "ðŸ–ðŸ¼", "ðŸ–ðŸ½", "ðŸ–ðŸ¾", "ðŸ–ðŸ¿"], version: "1.0" }, { emoji: "✋", category: 1, name: "raised hand", variations: ["✋ðŸ»", "✋ðŸ¼", "✋ðŸ½", "✋ðŸ¾", "✋ðŸ¿"], version: "1.0" }, { emoji: "🖖", category: 1, name: "vulcan salute", variations: ["🖖ðŸ»", "🖖ðŸ¼", "🖖ðŸ½", "🖖ðŸ¾", "🖖ðŸ¿"], version: "1.0" }, { emoji: "👌", category: 1, name: "OK hand", variations: ["👌ðŸ»", "👌ðŸ¼", "👌ðŸ½", "👌ðŸ¾", "👌ðŸ¿"], version: "1.0" }, { emoji: "🤌", category: 1, name: "pinched fingers", variations: ["🤌ðŸ»", "🤌ðŸ¼", "🤌ðŸ½", "🤌ðŸ¾", "🤌ðŸ¿"], version: "13.0" }, { emoji: "ðŸ¤", category: 1, name: "pinching hand", variations: ["ðŸ¤ðŸ»", "ðŸ¤ðŸ¼", "ðŸ¤ðŸ½", "ðŸ¤ðŸ¾", "ðŸ¤ðŸ¿"], version: "12.0" }, { emoji: "✌ï¸", category: 1, name: "victory hand", variations: ["✌ðŸ»", "✌ðŸ¼", "✌ðŸ½", "✌ðŸ¾", "✌ðŸ¿"], version: "1.0" }, { emoji: "🤞", category: 1, name: "crossed fingers", variations: ["🤞ðŸ»", "🤞ðŸ¼", "🤞ðŸ½", "🤞ðŸ¾", "🤞ðŸ¿"], version: "3.0" }, { emoji: "🤟", category: 1, name: "love-you gesture", variations: ["🤟ðŸ»", "🤟ðŸ¼", "🤟ðŸ½", "🤟ðŸ¾", "🤟ðŸ¿"], version: "5.0" }, { emoji: "🤘", category: 1, name: "sign of the horns", variations: ["🤘ðŸ»", "🤘ðŸ¼", "🤘ðŸ½", "🤘ðŸ¾", "🤘ðŸ¿"], version: "1.0" }, { emoji: "🤙", category: 1, name: "call me hand", variations: ["🤙ðŸ»", "🤙ðŸ¼", "🤙ðŸ½", "🤙ðŸ¾", "🤙ðŸ¿"], version: "3.0" }, { emoji: "👈", category: 1, name: "backhand index pointing left", variations: ["👈ðŸ»", "👈ðŸ¼", "👈ðŸ½", "👈ðŸ¾", "👈ðŸ¿"], version: "1.0" }, { emoji: "👉", category: 1, name: "backhand index pointing right", variations: ["👉ðŸ»", "👉ðŸ¼", "👉ðŸ½", "👉ðŸ¾", "👉ðŸ¿"], version: "1.0" }, { emoji: "👆", category: 1, name: "backhand index pointing up", variations: ["👆ðŸ»", "👆ðŸ¼", "👆ðŸ½", "👆ðŸ¾", "👆ðŸ¿"], version: "1.0" }, { emoji: "🖕", category: 1, name: "middle finger", variations: ["🖕ðŸ»", "🖕ðŸ¼", "🖕ðŸ½", "🖕ðŸ¾", "🖕ðŸ¿"], version: "1.0" }, { emoji: "👇", category: 1, name: "backhand index pointing down", variations: ["👇ðŸ»", "👇ðŸ¼", "👇ðŸ½", "👇ðŸ¾", "👇ðŸ¿"], version: "1.0" }, { emoji: "â˜ï¸", category: 1, name: "index pointing up", variations: ["â˜ðŸ»", "â˜ðŸ¼", "â˜ðŸ½", "â˜ðŸ¾", "â˜ðŸ¿"], version: "1.0" }, { emoji: "ðŸ‘", category: 1, name: "thumbs up", variations: ["ðŸ‘ðŸ»", "ðŸ‘ðŸ¼", "ðŸ‘ðŸ½", "ðŸ‘ðŸ¾", "ðŸ‘ðŸ¿"], version: "1.0" }, { emoji: "👎", category: 1, name: "thumbs down", variations: ["👎ðŸ»", "👎ðŸ¼", "👎ðŸ½", "👎ðŸ¾", "👎ðŸ¿"], version: "1.0" }, { emoji: "✊", category: 1, name: "raised fist", variations: ["✊ðŸ»", "✊ðŸ¼", "✊ðŸ½", "✊ðŸ¾", "✊ðŸ¿"], version: "1.0" }, { emoji: "👊", category: 1, name: "oncoming fist", variations: ["👊ðŸ»", "👊ðŸ¼", "👊ðŸ½", "👊ðŸ¾", "👊ðŸ¿"], version: "1.0" }, { emoji: "🤛", category: 1, name: "left-facing fist", variations: ["🤛ðŸ»", "🤛ðŸ¼", "🤛ðŸ½", "🤛ðŸ¾", "🤛ðŸ¿"], version: "3.0" }, { emoji: "🤜", category: 1, name: "right-facing fist", variations: ["🤜ðŸ»", "🤜ðŸ¼", "🤜ðŸ½", "🤜ðŸ¾", "🤜ðŸ¿"], version: "3.0" }, { emoji: "ðŸ‘", category: 1, name: "clapping hands", variations: ["ðŸ‘ðŸ»", "ðŸ‘ðŸ¼", "ðŸ‘ðŸ½", "ðŸ‘ðŸ¾", "ðŸ‘ðŸ¿"], version: "1.0" }, { emoji: "🙌", category: 1, name: "raising hands", variations: ["🙌ðŸ»", "🙌ðŸ¼", "🙌ðŸ½", "🙌ðŸ¾", "🙌ðŸ¿"], version: "1.0" }, { emoji: "ðŸ‘", category: 1, name: "open hands", variations: ["ðŸ‘ðŸ»", "ðŸ‘ðŸ¼", "ðŸ‘ðŸ½", "ðŸ‘ðŸ¾", "ðŸ‘ðŸ¿"], version: "1.0" }, { emoji: "🤲", category: 1, name: "palms up together", variations: ["🤲ðŸ»", "🤲ðŸ¼", "🤲ðŸ½", "🤲ðŸ¾", "🤲ðŸ¿"], version: "5.0" }, { emoji: "ðŸ¤", category: 1, name: "handshake", version: "3.0" }, { emoji: "ðŸ™", category: 1, name: "folded hands", variations: ["ðŸ™ðŸ»", "ðŸ™ðŸ¼", "ðŸ™ðŸ½", "ðŸ™ðŸ¾", "ðŸ™ðŸ¿"], version: "1.0" }, { emoji: "âœï¸", category: 1, name: "writing hand", variations: ["âœðŸ»", "âœðŸ¼", "âœðŸ½", "âœðŸ¾", "âœðŸ¿"], version: "1.0" }, { emoji: "💅", category: 1, name: "nail polish", variations: ["💅ðŸ»", "💅ðŸ¼", "💅ðŸ½", "💅ðŸ¾", "💅ðŸ¿"], version: "1.0" }, { emoji: "🤳", category: 1, name: "selfie", variations: ["🤳ðŸ»", "🤳ðŸ¼", "🤳ðŸ½", "🤳ðŸ¾", "🤳ðŸ¿"], version: "3.0" }, { emoji: "💪", category: 1, name: "flexed biceps", variations: ["💪ðŸ»", "💪ðŸ¼", "💪ðŸ½", "💪ðŸ¾", "💪ðŸ¿"], version: "1.0" }, { emoji: "🦾", category: 1, name: "mechanical arm", version: "12.0" }, { emoji: "🦿", category: 1, name: "mechanical leg", version: "12.0" }, { emoji: "🦵", category: 1, name: "leg", variations: ["🦵ðŸ»", "🦵ðŸ¼", "🦵ðŸ½", "🦵ðŸ¾", "🦵ðŸ¿"], version: "11.0" }, { emoji: "🦶", category: 1, name: "foot", variations: ["🦶ðŸ»", "🦶ðŸ¼", "🦶ðŸ½", "🦶ðŸ¾", "🦶ðŸ¿"], version: "11.0" }, { emoji: "👂", category: 1, name: "ear", variations: ["👂ðŸ»", "👂ðŸ¼", "👂ðŸ½", "👂ðŸ¾", "👂ðŸ¿"], version: "1.0" }, { emoji: "🦻", category: 1, name: "ear with hearing aid", variations: ["🦻ðŸ»", "🦻ðŸ¼", "🦻ðŸ½", "🦻ðŸ¾", "🦻ðŸ¿"], version: "12.0" }, { emoji: "👃", category: 1, name: "nose", variations: ["👃ðŸ»", "👃ðŸ¼", "👃ðŸ½", "👃ðŸ¾", "👃ðŸ¿"], version: "1.0" }, { emoji: "🧠", category: 1, name: "brain", version: "5.0" }, { emoji: "🫀", category: 1, name: "anatomical heart", version: "13.0" }, { emoji: "ðŸ«", category: 1, name: "lungs", version: "13.0" }, { emoji: "🦷", category: 1, name: "tooth", version: "11.0" }, { emoji: "🦴", category: 1, name: "bone", version: "11.0" }, { emoji: "👀", category: 1, name: "eyes", version: "1.0" }, { emoji: "ðŸ‘ï¸", category: 1, name: "eye", version: "1.0" }, { emoji: "👅", category: 1, name: "tongue", version: "1.0" }, { emoji: "👄", category: 1, name: "mouth", version: "1.0" }, { emoji: "👶", category: 1, name: "baby", variations: ["👶ðŸ»", "👶ðŸ¼", "👶ðŸ½", "👶ðŸ¾", "👶ðŸ¿"], version: "1.0" }, { emoji: "🧒", category: 1, name: "child", variations: ["🧒ðŸ»", "🧒ðŸ¼", "🧒ðŸ½", "🧒ðŸ¾", "🧒ðŸ¿"], version: "5.0" }, { emoji: "👦", category: 1, name: "boy", variations: ["👦ðŸ»", "👦ðŸ¼", "👦ðŸ½", "👦ðŸ¾", "👦ðŸ¿"], version: "1.0" }, { emoji: "👧", category: 1, name: "girl", variations: ["👧ðŸ»", "👧ðŸ¼", "👧ðŸ½", "👧ðŸ¾", "👧ðŸ¿"], version: "1.0" }, { emoji: "🧑", category: 1, name: "person", variations: ["🧑ðŸ»", "🧑ðŸ¼", "🧑ðŸ½", "🧑ðŸ¾", "🧑ðŸ¿"], version: "5.0" }, { emoji: "👱", category: 1, name: "person with blond hair", variations: ["👱ðŸ»", "👱ðŸ¼", "👱ðŸ½", "👱ðŸ¾", "👱ðŸ¿"], version: "1.0" }, { emoji: "👨", category: 1, name: "man", variations: ["👨ðŸ»", "👨ðŸ¼", "👨ðŸ½", "👨ðŸ¾", "👨ðŸ¿"], version: "1.0" }, { emoji: "🧔", category: 1, name: "man with beard", variations: ["🧔ðŸ»", "🧔ðŸ¼", "🧔ðŸ½", "🧔ðŸ¾", "🧔ðŸ¿"], version: "5.0" }, { emoji: "👨â€ðŸ¦°", category: 1, name: "man with red hair", variations: ["👨ðŸ»â€ðŸ¦°", "👨ðŸ¼â€ðŸ¦°", "👨ðŸ½â€ðŸ¦°", "👨ðŸ¾â€ðŸ¦°", "👨ðŸ¿â€ðŸ¦°"], version: "11.0" }, { emoji: "👨â€ðŸ¦±", category: 1, name: "man with curly hair", variations: ["👨ðŸ»â€ðŸ¦±", "👨ðŸ¼â€ðŸ¦±", "👨ðŸ½â€ðŸ¦±", "👨ðŸ¾â€ðŸ¦±", "👨ðŸ¿â€ðŸ¦±"], version: "11.0" }, { emoji: "👨â€ðŸ¦³", category: 1, name: "man with white hair", variations: ["👨ðŸ»â€ðŸ¦³", "👨ðŸ¼â€ðŸ¦³", "👨ðŸ½â€ðŸ¦³", "👨ðŸ¾â€ðŸ¦³", "👨ðŸ¿â€ðŸ¦³"], version: "11.0" }, { emoji: "👨â€ðŸ¦²", category: 1, name: "man with no hair", variations: ["👨ðŸ»â€ðŸ¦²", "👨ðŸ¼â€ðŸ¦²", "👨ðŸ½â€ðŸ¦²", "👨ðŸ¾â€ðŸ¦²", "👨ðŸ¿â€ðŸ¦²"], version: "11.0" }, { emoji: "👩", category: 1, name: "woman", variations: ["👩ðŸ»", "👩ðŸ¼", "👩ðŸ½", "👩ðŸ¾", "👩ðŸ¿"], version: "1.0" }, { emoji: "👩â€ðŸ¦°", category: 1, name: "woman with red hair", variations: ["👩ðŸ»â€ðŸ¦°", "👩ðŸ¼â€ðŸ¦°", "👩ðŸ½â€ðŸ¦°", "👩ðŸ¾â€ðŸ¦°", "👩ðŸ¿â€ðŸ¦°"], version: "11.0" }, { emoji: "🧑â€ðŸ¦°", category: 1, name: "person with red hair", variations: ["🧑ðŸ»â€ðŸ¦°", "🧑ðŸ¼â€ðŸ¦°", "🧑ðŸ½â€ðŸ¦°", "🧑ðŸ¾â€ðŸ¦°", "🧑ðŸ¿â€ðŸ¦°"], version: "12.1" }, { emoji: "👩â€ðŸ¦±", category: 1, name: "woman with curly hair", variations: ["👩ðŸ»â€ðŸ¦±", "👩ðŸ¼â€ðŸ¦±", "👩ðŸ½â€ðŸ¦±", "👩ðŸ¾â€ðŸ¦±", "👩ðŸ¿â€ðŸ¦±"], version: "11.0" }, { emoji: "🧑â€ðŸ¦±", category: 1, name: "person with curly hair", variations: ["🧑ðŸ»â€ðŸ¦±", "🧑ðŸ¼â€ðŸ¦±", "🧑ðŸ½â€ðŸ¦±", "🧑ðŸ¾â€ðŸ¦±", "🧑ðŸ¿â€ðŸ¦±"], version: "12.1" }, { emoji: "👩â€ðŸ¦³", category: 1, name: "woman with white hair", variations: ["👩ðŸ»â€ðŸ¦³", "👩ðŸ¼â€ðŸ¦³", "👩ðŸ½â€ðŸ¦³", "👩ðŸ¾â€ðŸ¦³", "👩ðŸ¿â€ðŸ¦³"], version: "11.0" }, { emoji: "🧑â€ðŸ¦³", category: 1, name: "person with white hair", variations: ["🧑ðŸ»â€ðŸ¦³", "🧑ðŸ¼â€ðŸ¦³", "🧑ðŸ½â€ðŸ¦³", "🧑ðŸ¾â€ðŸ¦³", "🧑ðŸ¿â€ðŸ¦³"], version: "12.1" }, { emoji: "👩â€ðŸ¦²", category: 1, name: "woman with no hair", variations: ["👩ðŸ»â€ðŸ¦²", "👩ðŸ¼â€ðŸ¦²", "👩ðŸ½â€ðŸ¦²", "👩ðŸ¾â€ðŸ¦²", "👩ðŸ¿â€ðŸ¦²"], version: "11.0" }, { emoji: "🧑â€ðŸ¦²", category: 1, name: "person with no hair", variations: ["🧑ðŸ»â€ðŸ¦²", "🧑ðŸ¼â€ðŸ¦²", "🧑ðŸ½â€ðŸ¦²", "🧑ðŸ¾â€ðŸ¦²", "🧑ðŸ¿â€ðŸ¦²"], version: "12.1" }, { emoji: "👱â€â™€ï¸", category: 1, name: "woman with blond hair", variations: ["👱ðŸ»â€â™€ï¸", "👱ðŸ¼â€â™€ï¸", "👱ðŸ½â€â™€ï¸", "👱ðŸ¾â€â™€ï¸", "👱ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "👱â€â™‚ï¸", category: 1, name: "man with blond hair", variations: ["👱ðŸ»â€â™‚ï¸", "👱ðŸ¼â€â™‚ï¸", "👱ðŸ½â€â™‚ï¸", "👱ðŸ¾â€â™‚ï¸", "👱ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "🧓", category: 1, name: "older person", variations: ["🧓ðŸ»", "🧓ðŸ¼", "🧓ðŸ½", "🧓ðŸ¾", "🧓ðŸ¿"], version: "5.0" }, { emoji: "👴", category: 1, name: "old man", variations: ["👴ðŸ»", "👴ðŸ¼", "👴ðŸ½", "👴ðŸ¾", "👴ðŸ¿"], version: "1.0" }, { emoji: "👵", category: 1, name: "old woman", variations: ["👵ðŸ»", "👵ðŸ¼", "👵ðŸ½", "👵ðŸ¾", "👵ðŸ¿"], version: "1.0" }, { emoji: "ðŸ™", category: 1, name: "person frowning", variations: ["ðŸ™ðŸ»", "ðŸ™ðŸ¼", "ðŸ™ðŸ½", "ðŸ™ðŸ¾", "ðŸ™ðŸ¿"], version: "1.0" }, { emoji: "ðŸ™â€â™‚ï¸", category: 1, name: "man frowning", variations: ["ðŸ™ðŸ»â€â™‚ï¸", "ðŸ™ðŸ¼â€â™‚ï¸", "ðŸ™ðŸ½â€â™‚ï¸", "ðŸ™ðŸ¾â€â™‚ï¸", "ðŸ™ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "ðŸ™â€â™€ï¸", category: 1, name: "woman frowning", variations: ["ðŸ™ðŸ»â€â™€ï¸", "ðŸ™ðŸ¼â€â™€ï¸", "ðŸ™ðŸ½â€â™€ï¸", "ðŸ™ðŸ¾â€â™€ï¸", "ðŸ™ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "🙎", category: 1, name: "person pouting", variations: ["🙎ðŸ»", "🙎ðŸ¼", "🙎ðŸ½", "🙎ðŸ¾", "🙎ðŸ¿"], version: "1.0" }, { emoji: "🙎â€â™‚ï¸", category: 1, name: "man pouting", variations: ["🙎ðŸ»â€â™‚ï¸", "🙎ðŸ¼â€â™‚ï¸", "🙎ðŸ½â€â™‚ï¸", "🙎ðŸ¾â€â™‚ï¸", "🙎ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "🙎â€â™€ï¸", category: 1, name: "woman pouting", variations: ["🙎ðŸ»â€â™€ï¸", "🙎ðŸ¼â€â™€ï¸", "🙎ðŸ½â€â™€ï¸", "🙎ðŸ¾â€â™€ï¸", "🙎ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "🙅", category: 1, name: "person gesturing NO", variations: ["🙅ðŸ»", "🙅ðŸ¼", "🙅ðŸ½", "🙅ðŸ¾", "🙅ðŸ¿"], version: "1.0" }, { emoji: "🙅â€â™‚ï¸", category: 1, name: "man gesturing NO", variations: ["🙅ðŸ»â€â™‚ï¸", "🙅ðŸ¼â€â™‚ï¸", "🙅ðŸ½â€â™‚ï¸", "🙅ðŸ¾â€â™‚ï¸", "🙅ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "🙅â€â™€ï¸", category: 1, name: "woman gesturing NO", variations: ["🙅ðŸ»â€â™€ï¸", "🙅ðŸ¼â€â™€ï¸", "🙅ðŸ½â€â™€ï¸", "🙅ðŸ¾â€â™€ï¸", "🙅ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "🙆", category: 1, name: "person gesturing OK", variations: ["🙆ðŸ»", "🙆ðŸ¼", "🙆ðŸ½", "🙆ðŸ¾", "🙆ðŸ¿"], version: "1.0" }, { emoji: "🙆â€â™‚ï¸", category: 1, name: "man gesturing OK", variations: ["🙆ðŸ»â€â™‚ï¸", "🙆ðŸ¼â€â™‚ï¸", "🙆ðŸ½â€â™‚ï¸", "🙆ðŸ¾â€â™‚ï¸", "🙆ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "🙆â€â™€ï¸", category: 1, name: "woman gesturing OK", variations: ["🙆ðŸ»â€â™€ï¸", "🙆ðŸ¼â€â™€ï¸", "🙆ðŸ½â€â™€ï¸", "🙆ðŸ¾â€â™€ï¸", "🙆ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "ðŸ’", category: 1, name: "person tipping hand", variations: ["ðŸ’ðŸ»", "ðŸ’ðŸ¼", "ðŸ’ðŸ½", "ðŸ’ðŸ¾", "ðŸ’ðŸ¿"], version: "1.0" }, { emoji: "ðŸ’â€â™‚ï¸", category: 1, name: "man tipping hand", variations: ["ðŸ’ðŸ»â€â™‚ï¸", "ðŸ’ðŸ¼â€â™‚ï¸", "ðŸ’ðŸ½â€â™‚ï¸", "ðŸ’ðŸ¾â€â™‚ï¸", "ðŸ’ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "ðŸ’â€â™€ï¸", category: 1, name: "woman tipping hand", variations: ["ðŸ’ðŸ»â€â™€ï¸", "ðŸ’ðŸ¼â€â™€ï¸", "ðŸ’ðŸ½â€â™€ï¸", "ðŸ’ðŸ¾â€â™€ï¸", "ðŸ’ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "🙋", category: 1, name: "person raising hand", variations: ["🙋ðŸ»", "🙋ðŸ¼", "🙋ðŸ½", "🙋ðŸ¾", "🙋ðŸ¿"], version: "1.0" }, { emoji: "🙋â€â™‚ï¸", category: 1, name: "man raising hand", variations: ["🙋ðŸ»â€â™‚ï¸", "🙋ðŸ¼â€â™‚ï¸", "🙋ðŸ½â€â™‚ï¸", "🙋ðŸ¾â€â™‚ï¸", "🙋ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "🙋â€â™€ï¸", category: 1, name: "woman raising hand", variations: ["🙋ðŸ»â€â™€ï¸", "🙋ðŸ¼â€â™€ï¸", "🙋ðŸ½â€â™€ï¸", "🙋ðŸ¾â€â™€ï¸", "🙋ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "ðŸ§", category: 1, name: "deaf person", variations: ["ðŸ§ðŸ»", "ðŸ§ðŸ¼", "ðŸ§ðŸ½", "ðŸ§ðŸ¾", "ðŸ§ðŸ¿"], version: "12.0" }, { emoji: "ðŸ§â€â™‚ï¸", category: 1, name: "deaf man", variations: ["ðŸ§ðŸ»â€â™‚ï¸", "ðŸ§ðŸ¼â€â™‚ï¸", "ðŸ§ðŸ½â€â™‚ï¸", "ðŸ§ðŸ¾â€â™‚ï¸", "ðŸ§ðŸ¿â€â™‚ï¸"], version: "12.0" }, { emoji: "ðŸ§â€â™€ï¸", category: 1, name: "deaf woman", variations: ["ðŸ§ðŸ»â€â™€ï¸", "ðŸ§ðŸ¼â€â™€ï¸", "ðŸ§ðŸ½â€â™€ï¸", "ðŸ§ðŸ¾â€â™€ï¸", "ðŸ§ðŸ¿â€â™€ï¸"], version: "12.0" }, { emoji: "🙇", category: 1, name: "person bowing", variations: ["🙇ðŸ»", "🙇ðŸ¼", "🙇ðŸ½", "🙇ðŸ¾", "🙇ðŸ¿"], version: "1.0" }, { emoji: "🙇â€â™‚ï¸", category: 1, name: "man bowing", variations: ["🙇ðŸ»â€â™‚ï¸", "🙇ðŸ¼â€â™‚ï¸", "🙇ðŸ½â€â™‚ï¸", "🙇ðŸ¾â€â™‚ï¸", "🙇ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "🙇â€â™€ï¸", category: 1, name: "woman bowing", variations: ["🙇ðŸ»â€â™€ï¸", "🙇ðŸ¼â€â™€ï¸", "🙇ðŸ½â€â™€ï¸", "🙇ðŸ¾â€â™€ï¸", "🙇ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "🤦", category: 1, name: "person facepalming", variations: ["🤦ðŸ»", "🤦ðŸ¼", "🤦ðŸ½", "🤦ðŸ¾", "🤦ðŸ¿"], version: "3.0" }, { emoji: "🤦â€â™‚ï¸", category: 1, name: "man facepalming", variations: ["🤦ðŸ»â€â™‚ï¸", "🤦ðŸ¼â€â™‚ï¸", "🤦ðŸ½â€â™‚ï¸", "🤦ðŸ¾â€â™‚ï¸", "🤦ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "🤦â€â™€ï¸", category: 1, name: "woman facepalming", variations: ["🤦ðŸ»â€â™€ï¸", "🤦ðŸ¼â€â™€ï¸", "🤦ðŸ½â€â™€ï¸", "🤦ðŸ¾â€â™€ï¸", "🤦ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "🤷", category: 1, name: "person shrugging", variations: ["🤷ðŸ»", "🤷ðŸ¼", "🤷ðŸ½", "🤷ðŸ¾", "🤷ðŸ¿"], version: "3.0" }, { emoji: "🤷â€â™‚ï¸", category: 1, name: "man shrugging", variations: ["🤷ðŸ»â€â™‚ï¸", "🤷ðŸ¼â€â™‚ï¸", "🤷ðŸ½â€â™‚ï¸", "🤷ðŸ¾â€â™‚ï¸", "🤷ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "🤷â€â™€ï¸", category: 1, name: "woman shrugging", variations: ["🤷ðŸ»â€â™€ï¸", "🤷ðŸ¼â€â™€ï¸", "🤷ðŸ½â€â™€ï¸", "🤷ðŸ¾â€â™€ï¸", "🤷ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "🧑â€âš•ï¸", category: 1, name: "health worker", variations: ["🧑ðŸ»â€âš•ï¸", "🧑ðŸ¼â€âš•ï¸", "🧑ðŸ½â€âš•ï¸", "🧑ðŸ¾â€âš•ï¸", "🧑ðŸ¿â€âš•ï¸"], version: "12.1" }, { emoji: "👨â€âš•ï¸", category: 1, name: "man health worker", variations: ["👨ðŸ»â€âš•ï¸", "👨ðŸ¼â€âš•ï¸", "👨ðŸ½â€âš•ï¸", "👨ðŸ¾â€âš•ï¸", "👨ðŸ¿â€âš•ï¸"], version: "4.0" }, { emoji: "👩â€âš•ï¸", category: 1, name: "woman health worker", variations: ["👩ðŸ»â€âš•ï¸", "👩ðŸ¼â€âš•ï¸", "👩ðŸ½â€âš•ï¸", "👩ðŸ¾â€âš•ï¸", "👩ðŸ¿â€âš•ï¸"], version: "4.0" }, { emoji: "🧑â€ðŸŽ“", category: 1, name: "student", variations: ["🧑ðŸ»â€ðŸŽ“", "🧑ðŸ¼â€ðŸŽ“", "🧑ðŸ½â€ðŸŽ“", "🧑ðŸ¾â€ðŸŽ“", "🧑ðŸ¿â€ðŸŽ“"], version: "12.1" }, { emoji: "👨â€ðŸŽ“", category: 1, name: "man student", variations: ["👨ðŸ»â€ðŸŽ“", "👨ðŸ¼â€ðŸŽ“", "👨ðŸ½â€ðŸŽ“", "👨ðŸ¾â€ðŸŽ“", "👨ðŸ¿â€ðŸŽ“"], version: "4.0" }, { emoji: "👩â€ðŸŽ“", category: 1, name: "woman student", variations: ["👩ðŸ»â€ðŸŽ“", "👩ðŸ¼â€ðŸŽ“", "👩ðŸ½â€ðŸŽ“", "👩ðŸ¾â€ðŸŽ“", "👩ðŸ¿â€ðŸŽ“"], version: "4.0" }, { emoji: "🧑â€ðŸ«", category: 1, name: "teacher", variations: ["🧑ðŸ»â€ðŸ«", "🧑ðŸ¼â€ðŸ«", "🧑ðŸ½â€ðŸ«", "🧑ðŸ¾â€ðŸ«", "🧑ðŸ¿â€ðŸ«"], version: "12.1" }, { emoji: "👨â€ðŸ«", category: 1, name: "man teacher", variations: ["👨ðŸ»â€ðŸ«", "👨ðŸ¼â€ðŸ«", "👨ðŸ½â€ðŸ«", "👨ðŸ¾â€ðŸ«", "👨ðŸ¿â€ðŸ«"], version: "4.0" }, { emoji: "👩â€ðŸ«", category: 1, name: "woman teacher", variations: ["👩ðŸ»â€ðŸ«", "👩ðŸ¼â€ðŸ«", "👩ðŸ½â€ðŸ«", "👩ðŸ¾â€ðŸ«", "👩ðŸ¿â€ðŸ«"], version: "4.0" }, { emoji: "🧑â€âš–ï¸", category: 1, name: "judge", variations: ["🧑ðŸ»â€âš–ï¸", "🧑ðŸ¼â€âš–ï¸", "🧑ðŸ½â€âš–ï¸", "🧑ðŸ¾â€âš–ï¸", "🧑ðŸ¿â€âš–ï¸"], version: "12.1" }, { emoji: "👨â€âš–ï¸", category: 1, name: "man judge", variations: ["👨ðŸ»â€âš–ï¸", "👨ðŸ¼â€âš–ï¸", "👨ðŸ½â€âš–ï¸", "👨ðŸ¾â€âš–ï¸", "👨ðŸ¿â€âš–ï¸"], version: "4.0" }, { emoji: "👩â€âš–ï¸", category: 1, name: "woman judge", variations: ["👩ðŸ»â€âš–ï¸", "👩ðŸ¼â€âš–ï¸", "👩ðŸ½â€âš–ï¸", "👩ðŸ¾â€âš–ï¸", "👩ðŸ¿â€âš–ï¸"], version: "4.0" }, { emoji: "🧑â€ðŸŒ¾", category: 1, name: "farmer", variations: ["🧑ðŸ»â€ðŸŒ¾", "🧑ðŸ¼â€ðŸŒ¾", "🧑ðŸ½â€ðŸŒ¾", "🧑ðŸ¾â€ðŸŒ¾", "🧑ðŸ¿â€ðŸŒ¾"], version: "12.1" }, { emoji: "👨â€ðŸŒ¾", category: 1, name: "man farmer", variations: ["👨ðŸ»â€ðŸŒ¾", "👨ðŸ¼â€ðŸŒ¾", "👨ðŸ½â€ðŸŒ¾", "👨ðŸ¾â€ðŸŒ¾", "👨ðŸ¿â€ðŸŒ¾"], version: "4.0" }, { emoji: "👩â€ðŸŒ¾", category: 1, name: "woman farmer", variations: ["👩ðŸ»â€ðŸŒ¾", "👩ðŸ¼â€ðŸŒ¾", "👩ðŸ½â€ðŸŒ¾", "👩ðŸ¾â€ðŸŒ¾", "👩ðŸ¿â€ðŸŒ¾"], version: "4.0" }, { emoji: "🧑â€ðŸ³", category: 1, name: "cook", variations: ["🧑ðŸ»â€ðŸ³", "🧑ðŸ¼â€ðŸ³", "🧑ðŸ½â€ðŸ³", "🧑ðŸ¾â€ðŸ³", "🧑ðŸ¿â€ðŸ³"], version: "12.1" }, { emoji: "👨â€ðŸ³", category: 1, name: "man cook", variations: ["👨ðŸ»â€ðŸ³", "👨ðŸ¼â€ðŸ³", "👨ðŸ½â€ðŸ³", "👨ðŸ¾â€ðŸ³", "👨ðŸ¿â€ðŸ³"], version: "4.0" }, { emoji: "👩â€ðŸ³", category: 1, name: "woman cook", variations: ["👩ðŸ»â€ðŸ³", "👩ðŸ¼â€ðŸ³", "👩ðŸ½â€ðŸ³", "👩ðŸ¾â€ðŸ³", "👩ðŸ¿â€ðŸ³"], version: "4.0" }, { emoji: "🧑â€ðŸ”§", category: 1, name: "mechanic", variations: ["🧑ðŸ»â€ðŸ”§", "🧑ðŸ¼â€ðŸ”§", "🧑ðŸ½â€ðŸ”§", "🧑ðŸ¾â€ðŸ”§", "🧑ðŸ¿â€ðŸ”§"], version: "12.1" }, { emoji: "👨â€ðŸ”§", category: 1, name: "man mechanic", variations: ["👨ðŸ»â€ðŸ”§", "👨ðŸ¼â€ðŸ”§", "👨ðŸ½â€ðŸ”§", "👨ðŸ¾â€ðŸ”§", "👨ðŸ¿â€ðŸ”§"], version: "4.0" }, { emoji: "👩â€ðŸ”§", category: 1, name: "woman mechanic", variations: ["👩ðŸ»â€ðŸ”§", "👩ðŸ¼â€ðŸ”§", "👩ðŸ½â€ðŸ”§", "👩ðŸ¾â€ðŸ”§", "👩ðŸ¿â€ðŸ”§"], version: "4.0" }, { emoji: "🧑â€ðŸ", category: 1, name: "factory worker", variations: ["🧑ðŸ»â€ðŸ", "🧑ðŸ¼â€ðŸ", "🧑ðŸ½â€ðŸ", "🧑ðŸ¾â€ðŸ", "🧑ðŸ¿â€ðŸ"], version: "12.1" }, { emoji: "👨â€ðŸ", category: 1, name: "man factory worker", variations: ["👨ðŸ»â€ðŸ", "👨ðŸ¼â€ðŸ", "👨ðŸ½â€ðŸ", "👨ðŸ¾â€ðŸ", "👨ðŸ¿â€ðŸ"], version: "4.0" }, { emoji: "👩â€ðŸ", category: 1, name: "woman factory worker", variations: ["👩ðŸ»â€ðŸ", "👩ðŸ¼â€ðŸ", "👩ðŸ½â€ðŸ", "👩ðŸ¾â€ðŸ", "👩ðŸ¿â€ðŸ"], version: "4.0" }, { emoji: "🧑â€ðŸ’¼", category: 1, name: "office worker", variations: ["🧑ðŸ»â€ðŸ’¼", "🧑ðŸ¼â€ðŸ’¼", "🧑ðŸ½â€ðŸ’¼", "🧑ðŸ¾â€ðŸ’¼", "🧑ðŸ¿â€ðŸ’¼"], version: "12.1" }, { emoji: "👨â€ðŸ’¼", category: 1, name: "man office worker", variations: ["👨ðŸ»â€ðŸ’¼", "👨ðŸ¼â€ðŸ’¼", "👨ðŸ½â€ðŸ’¼", "👨ðŸ¾â€ðŸ’¼", "👨ðŸ¿â€ðŸ’¼"], version: "4.0" }, { emoji: "👩â€ðŸ’¼", category: 1, name: "woman office worker", variations: ["👩ðŸ»â€ðŸ’¼", "👩ðŸ¼â€ðŸ’¼", "👩ðŸ½â€ðŸ’¼", "👩ðŸ¾â€ðŸ’¼", "👩ðŸ¿â€ðŸ’¼"], version: "4.0" }, { emoji: "🧑â€ðŸ”¬", category: 1, name: "scientist", variations: ["🧑ðŸ»â€ðŸ”¬", "🧑ðŸ¼â€ðŸ”¬", "🧑ðŸ½â€ðŸ”¬", "🧑ðŸ¾â€ðŸ”¬", "🧑ðŸ¿â€ðŸ”¬"], version: "12.1" }, { emoji: "👨â€ðŸ”¬", category: 1, name: "man scientist", variations: ["👨ðŸ»â€ðŸ”¬", "👨ðŸ¼â€ðŸ”¬", "👨ðŸ½â€ðŸ”¬", "👨ðŸ¾â€ðŸ”¬", "👨ðŸ¿â€ðŸ”¬"], version: "4.0" }, { emoji: "👩â€ðŸ”¬", category: 1, name: "woman scientist", variations: ["👩ðŸ»â€ðŸ”¬", "👩ðŸ¼â€ðŸ”¬", "👩ðŸ½â€ðŸ”¬", "👩ðŸ¾â€ðŸ”¬", "👩ðŸ¿â€ðŸ”¬"], version: "4.0" }, { emoji: "🧑â€ðŸ’»", category: 1, name: "technologist", variations: ["🧑ðŸ»â€ðŸ’»", "🧑ðŸ¼â€ðŸ’»", "🧑ðŸ½â€ðŸ’»", "🧑ðŸ¾â€ðŸ’»", "🧑ðŸ¿â€ðŸ’»"], version: "12.1" }, { emoji: "👨â€ðŸ’»", category: 1, name: "man technologist", variations: ["👨ðŸ»â€ðŸ’»", "👨ðŸ¼â€ðŸ’»", "👨ðŸ½â€ðŸ’»", "👨ðŸ¾â€ðŸ’»", "👨ðŸ¿â€ðŸ’»"], version: "4.0" }, { emoji: "👩â€ðŸ’»", category: 1, name: "woman technologist", variations: ["👩ðŸ»â€ðŸ’»", "👩ðŸ¼â€ðŸ’»", "👩ðŸ½â€ðŸ’»", "👩ðŸ¾â€ðŸ’»", "👩ðŸ¿â€ðŸ’»"], version: "4.0" }, { emoji: "🧑â€ðŸŽ¤", category: 1, name: "singer", variations: ["🧑ðŸ»â€ðŸŽ¤", "🧑ðŸ¼â€ðŸŽ¤", "🧑ðŸ½â€ðŸŽ¤", "🧑ðŸ¾â€ðŸŽ¤", "🧑ðŸ¿â€ðŸŽ¤"], version: "12.1" }, { emoji: "👨â€ðŸŽ¤", category: 1, name: "man singer", variations: ["👨ðŸ»â€ðŸŽ¤", "👨ðŸ¼â€ðŸŽ¤", "👨ðŸ½â€ðŸŽ¤", "👨ðŸ¾â€ðŸŽ¤", "👨ðŸ¿â€ðŸŽ¤"], version: "4.0" }, { emoji: "👩â€ðŸŽ¤", category: 1, name: "woman singer", variations: ["👩ðŸ»â€ðŸŽ¤", "👩ðŸ¼â€ðŸŽ¤", "👩ðŸ½â€ðŸŽ¤", "👩ðŸ¾â€ðŸŽ¤", "👩ðŸ¿â€ðŸŽ¤"], version: "4.0" }, { emoji: "🧑â€ðŸŽ¨", category: 1, name: "artist", variations: ["🧑ðŸ»â€ðŸŽ¨", "🧑ðŸ¼â€ðŸŽ¨", "🧑ðŸ½â€ðŸŽ¨", "🧑ðŸ¾â€ðŸŽ¨", "🧑ðŸ¿â€ðŸŽ¨"], version: "12.1" }, { emoji: "👨â€ðŸŽ¨", category: 1, name: "man artist", variations: ["👨ðŸ»â€ðŸŽ¨", "👨ðŸ¼â€ðŸŽ¨", "👨ðŸ½â€ðŸŽ¨", "👨ðŸ¾â€ðŸŽ¨", "👨ðŸ¿â€ðŸŽ¨"], version: "4.0" }, { emoji: "👩â€ðŸŽ¨", category: 1, name: "woman artist", variations: ["👩ðŸ»â€ðŸŽ¨", "👩ðŸ¼â€ðŸŽ¨", "👩ðŸ½â€ðŸŽ¨", "👩ðŸ¾â€ðŸŽ¨", "👩ðŸ¿â€ðŸŽ¨"], version: "4.0" }, { emoji: "🧑â€âœˆï¸", category: 1, name: "pilot", variations: ["🧑ðŸ»â€âœˆï¸", "🧑ðŸ¼â€âœˆï¸", "🧑ðŸ½â€âœˆï¸", "🧑ðŸ¾â€âœˆï¸", "🧑ðŸ¿â€âœˆï¸"], version: "12.1" }, { emoji: "👨â€âœˆï¸", category: 1, name: "man pilot", variations: ["👨ðŸ»â€âœˆï¸", "👨ðŸ¼â€âœˆï¸", "👨ðŸ½â€âœˆï¸", "👨ðŸ¾â€âœˆï¸", "👨ðŸ¿â€âœˆï¸"], version: "4.0" }, { emoji: "👩â€âœˆï¸", category: 1, name: "woman pilot", variations: ["👩ðŸ»â€âœˆï¸", "👩ðŸ¼â€âœˆï¸", "👩ðŸ½â€âœˆï¸", "👩ðŸ¾â€âœˆï¸", "👩ðŸ¿â€âœˆï¸"], version: "4.0" }, { emoji: "🧑â€ðŸš€", category: 1, name: "astronaut", variations: ["🧑ðŸ»â€ðŸš€", "🧑ðŸ¼â€ðŸš€", "🧑ðŸ½â€ðŸš€", "🧑ðŸ¾â€ðŸš€", "🧑ðŸ¿â€ðŸš€"], version: "12.1" }, { emoji: "👨â€ðŸš€", category: 1, name: "man astronaut", variations: ["👨ðŸ»â€ðŸš€", "👨ðŸ¼â€ðŸš€", "👨ðŸ½â€ðŸš€", "👨ðŸ¾â€ðŸš€", "👨ðŸ¿â€ðŸš€"], version: "4.0" }, { emoji: "👩â€ðŸš€", category: 1, name: "woman astronaut", variations: ["👩ðŸ»â€ðŸš€", "👩ðŸ¼â€ðŸš€", "👩ðŸ½â€ðŸš€", "👩ðŸ¾â€ðŸš€", "👩ðŸ¿â€ðŸš€"], version: "4.0" }, { emoji: "🧑â€ðŸš’", category: 1, name: "firefighter", variations: ["🧑ðŸ»â€ðŸš’", "🧑ðŸ¼â€ðŸš’", "🧑ðŸ½â€ðŸš’", "🧑ðŸ¾â€ðŸš’", "🧑ðŸ¿â€ðŸš’"], version: "12.1" }, { emoji: "👨â€ðŸš’", category: 1, name: "man firefighter", variations: ["👨ðŸ»â€ðŸš’", "👨ðŸ¼â€ðŸš’", "👨ðŸ½â€ðŸš’", "👨ðŸ¾â€ðŸš’", "👨ðŸ¿â€ðŸš’"], version: "4.0" }, { emoji: "👩â€ðŸš’", category: 1, name: "woman firefighter", variations: ["👩ðŸ»â€ðŸš’", "👩ðŸ¼â€ðŸš’", "👩ðŸ½â€ðŸš’", "👩ðŸ¾â€ðŸš’", "👩ðŸ¿â€ðŸš’"], version: "4.0" }, { emoji: "👮", category: 1, name: "police officer", variations: ["👮ðŸ»", "👮ðŸ¼", "👮ðŸ½", "👮ðŸ¾", "👮ðŸ¿"], version: "1.0" }, { emoji: "👮â€â™‚ï¸", category: 1, name: "man police officer", variations: ["👮ðŸ»â€â™‚ï¸", "👮ðŸ¼â€â™‚ï¸", "👮ðŸ½â€â™‚ï¸", "👮ðŸ¾â€â™‚ï¸", "👮ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "👮â€â™€ï¸", category: 1, name: "woman police officer", variations: ["👮ðŸ»â€â™€ï¸", "👮ðŸ¼â€â™€ï¸", "👮ðŸ½â€â™€ï¸", "👮ðŸ¾â€â™€ï¸", "👮ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "🕵ï¸", category: 1, name: "detective", variations: ["🕵ðŸ»", "🕵ðŸ¼", "🕵ðŸ½", "🕵ðŸ¾", "🕵ðŸ¿"], version: "1.0" }, { emoji: "🕵ï¸â€â™‚ï¸", category: 1, name: "man detective", variations: ["🕵ðŸ»â€â™‚ï¸", "🕵ðŸ¼â€â™‚ï¸", "🕵ðŸ½â€â™‚ï¸", "🕵ðŸ¾â€â™‚ï¸", "🕵ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "🕵ï¸â€â™€ï¸", category: 1, name: "woman detective", variations: ["🕵ðŸ»â€â™€ï¸", "🕵ðŸ¼â€â™€ï¸", "🕵ðŸ½â€â™€ï¸", "🕵ðŸ¾â€â™€ï¸", "🕵ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "💂", category: 1, name: "guard", variations: ["💂ðŸ»", "💂ðŸ¼", "💂ðŸ½", "💂ðŸ¾", "💂ðŸ¿"], version: "1.0" }, { emoji: "💂â€â™‚ï¸", category: 1, name: "man guard", variations: ["💂ðŸ»â€â™‚ï¸", "💂ðŸ¼â€â™‚ï¸", "💂ðŸ½â€â™‚ï¸", "💂ðŸ¾â€â™‚ï¸", "💂ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "💂â€â™€ï¸", category: 1, name: "woman guard", variations: ["💂ðŸ»â€â™€ï¸", "💂ðŸ¼â€â™€ï¸", "💂ðŸ½â€â™€ï¸", "💂ðŸ¾â€â™€ï¸", "💂ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "🥷", category: 1, name: "ninja", variations: ["🥷ðŸ»", "🥷ðŸ¼", "🥷ðŸ½", "🥷ðŸ¾", "🥷ðŸ¿"], version: "13.0" }, { emoji: "👷", category: 1, name: "construction worker", variations: ["👷ðŸ»", "👷ðŸ¼", "👷ðŸ½", "👷ðŸ¾", "👷ðŸ¿"], version: "1.0" }, { emoji: "👷â€â™‚ï¸", category: 1, name: "man construction worker", variations: ["👷ðŸ»â€â™‚ï¸", "👷ðŸ¼â€â™‚ï¸", "👷ðŸ½â€â™‚ï¸", "👷ðŸ¾â€â™‚ï¸", "👷ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "👷â€â™€ï¸", category: 1, name: "woman construction worker", variations: ["👷ðŸ»â€â™€ï¸", "👷ðŸ¼â€â™€ï¸", "👷ðŸ½â€â™€ï¸", "👷ðŸ¾â€â™€ï¸", "👷ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "🤴", category: 1, name: "prince", variations: ["🤴ðŸ»", "🤴ðŸ¼", "🤴ðŸ½", "🤴ðŸ¾", "🤴ðŸ¿"], version: "3.0" }, { emoji: "👸", category: 1, name: "princess", variations: ["👸ðŸ»", "👸ðŸ¼", "👸ðŸ½", "👸ðŸ¾", "👸ðŸ¿"], version: "1.0" }, { emoji: "👳", category: 1, name: "person wearing turban", variations: ["👳ðŸ»", "👳ðŸ¼", "👳ðŸ½", "👳ðŸ¾", "👳ðŸ¿"], version: "1.0" }, { emoji: "👳â€â™‚ï¸", category: 1, name: "man wearing turban", variations: ["👳ðŸ»â€â™‚ï¸", "👳ðŸ¼â€â™‚ï¸", "👳ðŸ½â€â™‚ï¸", "👳ðŸ¾â€â™‚ï¸", "👳ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "👳â€â™€ï¸", category: 1, name: "woman wearing turban", variations: ["👳ðŸ»â€â™€ï¸", "👳ðŸ¼â€â™€ï¸", "👳ðŸ½â€â™€ï¸", "👳ðŸ¾â€â™€ï¸", "👳ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "👲", category: 1, name: "person with skullcap", variations: ["👲ðŸ»", "👲ðŸ¼", "👲ðŸ½", "👲ðŸ¾", "👲ðŸ¿"], version: "1.0" }, { emoji: "🧕", category: 1, name: "woman with headscarf", variations: ["🧕ðŸ»", "🧕ðŸ¼", "🧕ðŸ½", "🧕ðŸ¾", "🧕ðŸ¿"], version: "5.0" }, { emoji: "🤵", category: 1, name: "person in tuxedo", variations: ["🤵ðŸ»", "🤵ðŸ¼", "🤵ðŸ½", "🤵ðŸ¾", "🤵ðŸ¿"], version: "3.0" }, { emoji: "🤵â€â™‚ï¸", category: 1, name: "man in tuxedo", variations: ["🤵ðŸ»â€â™‚ï¸", "🤵ðŸ¼â€â™‚ï¸", "🤵ðŸ½â€â™‚ï¸", "🤵ðŸ¾â€â™‚ï¸", "🤵ðŸ¿â€â™‚ï¸"], version: "13.0" }, { emoji: "🤵â€â™€ï¸", category: 1, name: "woman in tuxedo", variations: ["🤵ðŸ»â€â™€ï¸", "🤵ðŸ¼â€â™€ï¸", "🤵ðŸ½â€â™€ï¸", "🤵ðŸ¾â€â™€ï¸", "🤵ðŸ¿â€â™€ï¸"], version: "13.0" }, { emoji: "👰", category: 1, name: "person with veil", variations: ["👰ðŸ»", "👰ðŸ¼", "👰ðŸ½", "👰ðŸ¾", "👰ðŸ¿"], version: "1.0" }, { emoji: "👰â€â™‚ï¸", category: 1, name: "man with veil", variations: ["👰ðŸ»â€â™‚ï¸", "👰ðŸ¼â€â™‚ï¸", "👰ðŸ½â€â™‚ï¸", "👰ðŸ¾â€â™‚ï¸", "👰ðŸ¿â€â™‚ï¸"], version: "13.0" }, { emoji: "👰â€â™€ï¸", category: 1, name: "woman with veil", variations: ["👰ðŸ»â€â™€ï¸", "👰ðŸ¼â€â™€ï¸", "👰ðŸ½â€â™€ï¸", "👰ðŸ¾â€â™€ï¸", "👰ðŸ¿â€â™€ï¸"], version: "13.0" }, { emoji: "🤰", category: 1, name: "pregnant woman", variations: ["🤰ðŸ»", "🤰ðŸ¼", "🤰ðŸ½", "🤰ðŸ¾", "🤰ðŸ¿"], version: "3.0" }, { emoji: "🤱", category: 1, name: "breast-feeding", variations: ["🤱ðŸ»", "🤱ðŸ¼", "🤱ðŸ½", "🤱ðŸ¾", "🤱ðŸ¿"], version: "5.0" }, { emoji: "👩â€ðŸ¼", category: 1, name: "woman feeding baby", variations: ["👩ðŸ»â€ðŸ¼", "👩ðŸ¼â€ðŸ¼", "👩ðŸ½â€ðŸ¼", "👩ðŸ¾â€ðŸ¼", "👩ðŸ¿â€ðŸ¼"], version: "13.0" }, { emoji: "👨â€ðŸ¼", category: 1, name: "man feeding baby", variations: ["👨ðŸ»â€ðŸ¼", "👨ðŸ¼â€ðŸ¼", "👨ðŸ½â€ðŸ¼", "👨ðŸ¾â€ðŸ¼", "👨ðŸ¿â€ðŸ¼"], version: "13.0" }, { emoji: "🧑â€ðŸ¼", category: 1, name: "person feeding baby", variations: ["🧑ðŸ»â€ðŸ¼", "🧑ðŸ¼â€ðŸ¼", "🧑ðŸ½â€ðŸ¼", "🧑ðŸ¾â€ðŸ¼", "🧑ðŸ¿â€ðŸ¼"], version: "13.0" }, { emoji: "👼", category: 1, name: "baby angel", variations: ["👼ðŸ»", "👼ðŸ¼", "👼ðŸ½", "👼ðŸ¾", "👼ðŸ¿"], version: "1.0" }, { emoji: "🎅", category: 1, name: "Santa Claus", variations: ["🎅ðŸ»", "🎅ðŸ¼", "🎅ðŸ½", "🎅ðŸ¾", "🎅ðŸ¿"], version: "1.0" }, { emoji: "🤶", category: 1, name: "Mrs. Claus", variations: ["🤶ðŸ»", "🤶ðŸ¼", "🤶ðŸ½", "🤶ðŸ¾", "🤶ðŸ¿"], version: "3.0" }, { emoji: "🧑â€ðŸŽ„", category: 1, name: "mx claus", variations: ["🧑ðŸ»â€ðŸŽ„", "🧑ðŸ¼â€ðŸŽ„", "🧑ðŸ½â€ðŸŽ„", "🧑ðŸ¾â€ðŸŽ„", "🧑ðŸ¿â€ðŸŽ„"], version: "13.0" }, { emoji: "🦸", category: 1, name: "superhero", variations: ["🦸ðŸ»", "🦸ðŸ¼", "🦸ðŸ½", "🦸ðŸ¾", "🦸ðŸ¿"], version: "11.0" }, { emoji: "🦸â€â™‚ï¸", category: 1, name: "man superhero", variations: ["🦸ðŸ»â€â™‚ï¸", "🦸ðŸ¼â€â™‚ï¸", "🦸ðŸ½â€â™‚ï¸", "🦸ðŸ¾â€â™‚ï¸", "🦸ðŸ¿â€â™‚ï¸"], version: "11.0" }, { emoji: "🦸â€â™€ï¸", category: 1, name: "woman superhero", variations: ["🦸ðŸ»â€â™€ï¸", "🦸ðŸ¼â€â™€ï¸", "🦸ðŸ½â€â™€ï¸", "🦸ðŸ¾â€â™€ï¸", "🦸ðŸ¿â€â™€ï¸"], version: "11.0" }, { emoji: "🦹", category: 1, name: "supervillain", variations: ["🦹ðŸ»", "🦹ðŸ¼", "🦹ðŸ½", "🦹ðŸ¾", "🦹ðŸ¿"], version: "11.0" }, { emoji: "🦹â€â™‚ï¸", category: 1, name: "man supervillain", variations: ["🦹ðŸ»â€â™‚ï¸", "🦹ðŸ¼â€â™‚ï¸", "🦹ðŸ½â€â™‚ï¸", "🦹ðŸ¾â€â™‚ï¸", "🦹ðŸ¿â€â™‚ï¸"], version: "11.0" }, { emoji: "🦹â€â™€ï¸", category: 1, name: "woman supervillain", variations: ["🦹ðŸ»â€â™€ï¸", "🦹ðŸ¼â€â™€ï¸", "🦹ðŸ½â€â™€ï¸", "🦹ðŸ¾â€â™€ï¸", "🦹ðŸ¿â€â™€ï¸"], version: "11.0" }, { emoji: "🧙", category: 1, name: "mage", variations: ["🧙ðŸ»", "🧙ðŸ¼", "🧙ðŸ½", "🧙ðŸ¾", "🧙ðŸ¿"], version: "5.0" }, { emoji: "🧙â€â™‚ï¸", category: 1, name: "man mage", variations: ["🧙ðŸ»â€â™‚ï¸", "🧙ðŸ¼â€â™‚ï¸", "🧙ðŸ½â€â™‚ï¸", "🧙ðŸ¾â€â™‚ï¸", "🧙ðŸ¿â€â™‚ï¸"], version: "5.0" }, { emoji: "🧙â€â™€ï¸", category: 1, name: "woman mage", variations: ["🧙ðŸ»â€â™€ï¸", "🧙ðŸ¼â€â™€ï¸", "🧙ðŸ½â€â™€ï¸", "🧙ðŸ¾â€â™€ï¸", "🧙ðŸ¿â€â™€ï¸"], version: "5.0" }, { emoji: "🧚", category: 1, name: "fairy", variations: ["🧚ðŸ»", "🧚ðŸ¼", "🧚ðŸ½", "🧚ðŸ¾", "🧚ðŸ¿"], version: "5.0" }, { emoji: "🧚â€â™‚ï¸", category: 1, name: "man fairy", variations: ["🧚ðŸ»â€â™‚ï¸", "🧚ðŸ¼â€â™‚ï¸", "🧚ðŸ½â€â™‚ï¸", "🧚ðŸ¾â€â™‚ï¸", "🧚ðŸ¿â€â™‚ï¸"], version: "5.0" }, { emoji: "🧚â€â™€ï¸", category: 1, name: "woman fairy", variations: ["🧚ðŸ»â€â™€ï¸", "🧚ðŸ¼â€â™€ï¸", "🧚ðŸ½â€â™€ï¸", "🧚ðŸ¾â€â™€ï¸", "🧚ðŸ¿â€â™€ï¸"], version: "5.0" }, { emoji: "🧛", category: 1, name: "vampire", variations: ["🧛ðŸ»", "🧛ðŸ¼", "🧛ðŸ½", "🧛ðŸ¾", "🧛ðŸ¿"], version: "5.0" }, { emoji: "🧛â€â™‚ï¸", category: 1, name: "man vampire", variations: ["🧛ðŸ»â€â™‚ï¸", "🧛ðŸ¼â€â™‚ï¸", "🧛ðŸ½â€â™‚ï¸", "🧛ðŸ¾â€â™‚ï¸", "🧛ðŸ¿â€â™‚ï¸"], version: "5.0" }, { emoji: "🧛â€â™€ï¸", category: 1, name: "woman vampire", variations: ["🧛ðŸ»â€â™€ï¸", "🧛ðŸ¼â€â™€ï¸", "🧛ðŸ½â€â™€ï¸", "🧛ðŸ¾â€â™€ï¸", "🧛ðŸ¿â€â™€ï¸"], version: "5.0" }, { emoji: "🧜", category: 1, name: "merperson", variations: ["🧜ðŸ»", "🧜ðŸ¼", "🧜ðŸ½", "🧜ðŸ¾", "🧜ðŸ¿"], version: "5.0" }, { emoji: "🧜â€â™‚ï¸", category: 1, name: "merman", variations: ["🧜ðŸ»â€â™‚ï¸", "🧜ðŸ¼â€â™‚ï¸", "🧜ðŸ½â€â™‚ï¸", "🧜ðŸ¾â€â™‚ï¸", "🧜ðŸ¿â€â™‚ï¸"], version: "5.0" }, { emoji: "🧜â€â™€ï¸", category: 1, name: "mermaid", variations: ["🧜ðŸ»â€â™€ï¸", "🧜ðŸ¼â€â™€ï¸", "🧜ðŸ½â€â™€ï¸", "🧜ðŸ¾â€â™€ï¸", "🧜ðŸ¿â€â™€ï¸"], version: "5.0" }, { emoji: "ðŸ§", category: 1, name: "elf", variations: ["ðŸ§ðŸ»", "ðŸ§ðŸ¼", "ðŸ§ðŸ½", "ðŸ§ðŸ¾", "ðŸ§ðŸ¿"], version: "5.0" }, { emoji: "ðŸ§â€â™‚ï¸", category: 1, name: "man elf", variations: ["ðŸ§ðŸ»â€â™‚ï¸", "ðŸ§ðŸ¼â€â™‚ï¸", "ðŸ§ðŸ½â€â™‚ï¸", "ðŸ§ðŸ¾â€â™‚ï¸", "ðŸ§ðŸ¿â€â™‚ï¸"], version: "5.0" }, { emoji: "ðŸ§â€â™€ï¸", category: 1, name: "woman elf", variations: ["ðŸ§ðŸ»â€â™€ï¸", "ðŸ§ðŸ¼â€â™€ï¸", "ðŸ§ðŸ½â€â™€ï¸", "ðŸ§ðŸ¾â€â™€ï¸", "ðŸ§ðŸ¿â€â™€ï¸"], version: "5.0" }, { emoji: "🧞", category: 1, name: "genie", version: "5.0" }, { emoji: "🧞â€â™‚ï¸", category: 1, name: "man genie", version: "5.0" }, { emoji: "🧞â€â™€ï¸", category: 1, name: "woman genie", version: "5.0" }, { emoji: "🧟", category: 1, name: "zombie", version: "5.0" }, { emoji: "🧟â€â™‚ï¸", category: 1, name: "man zombie", version: "5.0" }, { emoji: "🧟â€â™€ï¸", category: 1, name: "woman zombie", version: "5.0" }, { emoji: "💆", category: 1, name: "person getting massage", variations: ["💆ðŸ»", "💆ðŸ¼", "💆ðŸ½", "💆ðŸ¾", "💆ðŸ¿"], version: "1.0" }, { emoji: "💆â€â™‚ï¸", category: 1, name: "man getting massage", variations: ["💆ðŸ»â€â™‚ï¸", "💆ðŸ¼â€â™‚ï¸", "💆ðŸ½â€â™‚ï¸", "💆ðŸ¾â€â™‚ï¸", "💆ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "💆â€â™€ï¸", category: 1, name: "woman getting massage", variations: ["💆ðŸ»â€â™€ï¸", "💆ðŸ¼â€â™€ï¸", "💆ðŸ½â€â™€ï¸", "💆ðŸ¾â€â™€ï¸", "💆ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "💇", category: 1, name: "person getting haircut", variations: ["💇ðŸ»", "💇ðŸ¼", "💇ðŸ½", "💇ðŸ¾", "💇ðŸ¿"], version: "1.0" }, { emoji: "💇â€â™‚ï¸", category: 1, name: "man getting haircut", variations: ["💇ðŸ»â€â™‚ï¸", "💇ðŸ¼â€â™‚ï¸", "💇ðŸ½â€â™‚ï¸", "💇ðŸ¾â€â™‚ï¸", "💇ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "💇â€â™€ï¸", category: 1, name: "woman getting haircut", variations: ["💇ðŸ»â€â™€ï¸", "💇ðŸ¼â€â™€ï¸", "💇ðŸ½â€â™€ï¸", "💇ðŸ¾â€â™€ï¸", "💇ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "🚶", category: 1, name: "person walking", variations: ["🚶ðŸ»", "🚶ðŸ¼", "🚶ðŸ½", "🚶ðŸ¾", "🚶ðŸ¿"], version: "1.0" }, { emoji: "🚶â€â™‚ï¸", category: 1, name: "man walking", variations: ["🚶ðŸ»â€â™‚ï¸", "🚶ðŸ¼â€â™‚ï¸", "🚶ðŸ½â€â™‚ï¸", "🚶ðŸ¾â€â™‚ï¸", "🚶ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "🚶â€â™€ï¸", category: 1, name: "woman walking", variations: ["🚶ðŸ»â€â™€ï¸", "🚶ðŸ¼â€â™€ï¸", "🚶ðŸ½â€â™€ï¸", "🚶ðŸ¾â€â™€ï¸", "🚶ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "ðŸ§", category: 1, name: "person standing", variations: ["ðŸ§ðŸ»", "ðŸ§ðŸ¼", "ðŸ§ðŸ½", "ðŸ§ðŸ¾", "ðŸ§ðŸ¿"], version: "12.0" }, { emoji: "ðŸ§â€â™‚ï¸", category: 1, name: "man standing", variations: ["ðŸ§ðŸ»â€â™‚ï¸", "ðŸ§ðŸ¼â€â™‚ï¸", "ðŸ§ðŸ½â€â™‚ï¸", "ðŸ§ðŸ¾â€â™‚ï¸", "ðŸ§ðŸ¿â€â™‚ï¸"], version: "12.0" }, { emoji: "ðŸ§â€â™€ï¸", category: 1, name: "woman standing", variations: ["ðŸ§ðŸ»â€â™€ï¸", "ðŸ§ðŸ¼â€â™€ï¸", "ðŸ§ðŸ½â€â™€ï¸", "ðŸ§ðŸ¾â€â™€ï¸", "ðŸ§ðŸ¿â€â™€ï¸"], version: "12.0" }, { emoji: "🧎", category: 1, name: "person kneeling", variations: ["🧎ðŸ»", "🧎ðŸ¼", "🧎ðŸ½", "🧎ðŸ¾", "🧎ðŸ¿"], version: "12.0" }, { emoji: "🧎â€â™‚ï¸", category: 1, name: "man kneeling", variations: ["🧎ðŸ»â€â™‚ï¸", "🧎ðŸ¼â€â™‚ï¸", "🧎ðŸ½â€â™‚ï¸", "🧎ðŸ¾â€â™‚ï¸", "🧎ðŸ¿â€â™‚ï¸"], version: "12.0" }, { emoji: "🧎â€â™€ï¸", category: 1, name: "woman kneeling", variations: ["🧎ðŸ»â€â™€ï¸", "🧎ðŸ¼â€â™€ï¸", "🧎ðŸ½â€â™€ï¸", "🧎ðŸ¾â€â™€ï¸", "🧎ðŸ¿â€â™€ï¸"], version: "12.0" }, { emoji: "🧑â€ðŸ¦¯", category: 1, name: "person with white cane", variations: ["🧑ðŸ»â€ðŸ¦¯", "🧑ðŸ¼â€ðŸ¦¯", "🧑ðŸ½â€ðŸ¦¯", "🧑ðŸ¾â€ðŸ¦¯", "🧑ðŸ¿â€ðŸ¦¯"], version: "12.1" }, { emoji: "👨â€ðŸ¦¯", category: 1, name: "man with white cane", variations: ["👨ðŸ»â€ðŸ¦¯", "👨ðŸ¼â€ðŸ¦¯", "👨ðŸ½â€ðŸ¦¯", "👨ðŸ¾â€ðŸ¦¯", "👨ðŸ¿â€ðŸ¦¯"], version: "12.0" }, { emoji: "👩â€ðŸ¦¯", category: 1, name: "woman with white cane", variations: ["👩ðŸ»â€ðŸ¦¯", "👩ðŸ¼â€ðŸ¦¯", "👩ðŸ½â€ðŸ¦¯", "👩ðŸ¾â€ðŸ¦¯", "👩ðŸ¿â€ðŸ¦¯"], version: "12.0" }, { emoji: "🧑â€ðŸ¦¼", category: 1, name: "person in motorized wheelchair", variations: ["🧑ðŸ»â€ðŸ¦¼", "🧑ðŸ¼â€ðŸ¦¼", "🧑ðŸ½â€ðŸ¦¼", "🧑ðŸ¾â€ðŸ¦¼", "🧑ðŸ¿â€ðŸ¦¼"], version: "12.1" }, { emoji: "👨â€ðŸ¦¼", category: 1, name: "man in motorized wheelchair", variations: ["👨ðŸ»â€ðŸ¦¼", "👨ðŸ¼â€ðŸ¦¼", "👨ðŸ½â€ðŸ¦¼", "👨ðŸ¾â€ðŸ¦¼", "👨ðŸ¿â€ðŸ¦¼"], version: "12.0" }, { emoji: "👩â€ðŸ¦¼", category: 1, name: "woman in motorized wheelchair", variations: ["👩ðŸ»â€ðŸ¦¼", "👩ðŸ¼â€ðŸ¦¼", "👩ðŸ½â€ðŸ¦¼", "👩ðŸ¾â€ðŸ¦¼", "👩ðŸ¿â€ðŸ¦¼"], version: "12.0" }, { emoji: "🧑â€ðŸ¦½", category: 1, name: "person in manual wheelchair", variations: ["🧑ðŸ»â€ðŸ¦½", "🧑ðŸ¼â€ðŸ¦½", "🧑ðŸ½â€ðŸ¦½", "🧑ðŸ¾â€ðŸ¦½", "🧑ðŸ¿â€ðŸ¦½"], version: "12.1" }, { emoji: "👨â€ðŸ¦½", category: 1, name: "man in manual wheelchair", variations: ["👨ðŸ»â€ðŸ¦½", "👨ðŸ¼â€ðŸ¦½", "👨ðŸ½â€ðŸ¦½", "👨ðŸ¾â€ðŸ¦½", "👨ðŸ¿â€ðŸ¦½"], version: "12.0" }, { emoji: "👩â€ðŸ¦½", category: 1, name: "woman in manual wheelchair", variations: ["👩ðŸ»â€ðŸ¦½", "👩ðŸ¼â€ðŸ¦½", "👩ðŸ½â€ðŸ¦½", "👩ðŸ¾â€ðŸ¦½", "👩ðŸ¿â€ðŸ¦½"], version: "12.0" }, { emoji: "ðŸƒ", category: 1, name: "person running", variations: ["ðŸƒðŸ»", "ðŸƒðŸ¼", "ðŸƒðŸ½", "ðŸƒðŸ¾", "ðŸƒðŸ¿"], version: "1.0" }, { emoji: "ðŸƒâ€â™‚ï¸", category: 1, name: "man running", variations: ["ðŸƒðŸ»â€â™‚ï¸", "ðŸƒðŸ¼â€â™‚ï¸", "ðŸƒðŸ½â€â™‚ï¸", "ðŸƒðŸ¾â€â™‚ï¸", "ðŸƒðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "ðŸƒâ€â™€ï¸", category: 1, name: "woman running", variations: ["ðŸƒðŸ»â€â™€ï¸", "ðŸƒðŸ¼â€â™€ï¸", "ðŸƒðŸ½â€â™€ï¸", "ðŸƒðŸ¾â€â™€ï¸", "ðŸƒðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "💃", category: 1, name: "woman dancing", variations: ["💃ðŸ»", "💃ðŸ¼", "💃ðŸ½", "💃ðŸ¾", "💃ðŸ¿"], version: "1.0" }, { emoji: "🕺", category: 1, name: "man dancing", variations: ["🕺ðŸ»", "🕺ðŸ¼", "🕺ðŸ½", "🕺ðŸ¾", "🕺ðŸ¿"], version: "3.0" }, { emoji: "🕴ï¸", category: 1, name: "person in suit levitating", variations: ["🕴ðŸ»", "🕴ðŸ¼", "🕴ðŸ½", "🕴ðŸ¾", "🕴ðŸ¿"], version: "1.0" }, { emoji: "👯", category: 1, name: "people with bunny ears", version: "1.0" }, { emoji: "👯â€â™‚ï¸", category: 1, name: "men with bunny ears", version: "4.0" }, { emoji: "👯â€â™€ï¸", category: 1, name: "women with bunny ears", version: "4.0" }, { emoji: "🧖", category: 1, name: "person in steamy room", variations: ["🧖ðŸ»", "🧖ðŸ¼", "🧖ðŸ½", "🧖ðŸ¾", "🧖ðŸ¿"], version: "5.0" }, { emoji: "🧖â€â™‚ï¸", category: 1, name: "man in steamy room", variations: ["🧖ðŸ»â€â™‚ï¸", "🧖ðŸ¼â€â™‚ï¸", "🧖ðŸ½â€â™‚ï¸", "🧖ðŸ¾â€â™‚ï¸", "🧖ðŸ¿â€â™‚ï¸"], version: "5.0" }, { emoji: "🧖â€â™€ï¸", category: 1, name: "woman in steamy room", variations: ["🧖ðŸ»â€â™€ï¸", "🧖ðŸ¼â€â™€ï¸", "🧖ðŸ½â€â™€ï¸", "🧖ðŸ¾â€â™€ï¸", "🧖ðŸ¿â€â™€ï¸"], version: "5.0" }, { emoji: "🧗", category: 1, name: "person climbing", variations: ["🧗ðŸ»", "🧗ðŸ¼", "🧗ðŸ½", "🧗ðŸ¾", "🧗ðŸ¿"], version: "5.0" }, { emoji: "🧗â€â™‚ï¸", category: 1, name: "man climbing", variations: ["🧗ðŸ»â€â™‚ï¸", "🧗ðŸ¼â€â™‚ï¸", "🧗ðŸ½â€â™‚ï¸", "🧗ðŸ¾â€â™‚ï¸", "🧗ðŸ¿â€â™‚ï¸"], version: "5.0" }, { emoji: "🧗â€â™€ï¸", category: 1, name: "woman climbing", variations: ["🧗ðŸ»â€â™€ï¸", "🧗ðŸ¼â€â™€ï¸", "🧗ðŸ½â€â™€ï¸", "🧗ðŸ¾â€â™€ï¸", "🧗ðŸ¿â€â™€ï¸"], version: "5.0" }, { emoji: "🤺", category: 1, name: "person fencing", version: "3.0" }, { emoji: "ðŸ‡", category: 1, name: "horse racing", variations: ["ðŸ‡ðŸ»", "ðŸ‡ðŸ¼", "ðŸ‡ðŸ½", "ðŸ‡ðŸ¾", "ðŸ‡ðŸ¿"], version: "1.0" }, { emoji: "â›·ï¸", category: 1, name: "skier", version: "1.0" }, { emoji: "ðŸ‚", category: 1, name: "snowboarder", variations: ["ðŸ‚ðŸ»", "ðŸ‚ðŸ¼", "ðŸ‚ðŸ½", "ðŸ‚ðŸ¾", "ðŸ‚ðŸ¿"], version: "1.0" }, { emoji: "ðŸŒï¸", category: 1, name: "person golfing", variations: ["ðŸŒðŸ»", "ðŸŒðŸ¼", "ðŸŒðŸ½", "ðŸŒðŸ¾", "ðŸŒðŸ¿"], version: "1.0" }, { emoji: "ðŸŒï¸â€â™‚ï¸", category: 1, name: "man golfing", variations: ["ðŸŒðŸ»â€â™‚ï¸", "ðŸŒðŸ¼â€â™‚ï¸", "ðŸŒðŸ½â€â™‚ï¸", "ðŸŒðŸ¾â€â™‚ï¸", "ðŸŒðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "ðŸŒï¸â€â™€ï¸", category: 1, name: "woman golfing", variations: ["ðŸŒðŸ»â€â™€ï¸", "ðŸŒðŸ¼â€â™€ï¸", "ðŸŒðŸ½â€â™€ï¸", "ðŸŒðŸ¾â€â™€ï¸", "ðŸŒðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "ðŸ„", category: 1, name: "person surfing", variations: ["ðŸ„ðŸ»", "ðŸ„ðŸ¼", "ðŸ„ðŸ½", "ðŸ„ðŸ¾", "ðŸ„ðŸ¿"], version: "1.0" }, { emoji: "ðŸ„â€â™‚ï¸", category: 1, name: "man surfing", variations: ["ðŸ„ðŸ»â€â™‚ï¸", "ðŸ„ðŸ¼â€â™‚ï¸", "ðŸ„ðŸ½â€â™‚ï¸", "ðŸ„ðŸ¾â€â™‚ï¸", "ðŸ„ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "ðŸ„â€â™€ï¸", category: 1, name: "woman surfing", variations: ["ðŸ„ðŸ»â€â™€ï¸", "ðŸ„ðŸ¼â€â™€ï¸", "ðŸ„ðŸ½â€â™€ï¸", "ðŸ„ðŸ¾â€â™€ï¸", "ðŸ„ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "🚣", category: 1, name: "person rowing boat", variations: ["🚣ðŸ»", "🚣ðŸ¼", "🚣ðŸ½", "🚣ðŸ¾", "🚣ðŸ¿"], version: "1.0" }, { emoji: "🚣â€â™‚ï¸", category: 1, name: "man rowing boat", variations: ["🚣ðŸ»â€â™‚ï¸", "🚣ðŸ¼â€â™‚ï¸", "🚣ðŸ½â€â™‚ï¸", "🚣ðŸ¾â€â™‚ï¸", "🚣ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "🚣â€â™€ï¸", category: 1, name: "woman rowing boat", variations: ["🚣ðŸ»â€â™€ï¸", "🚣ðŸ¼â€â™€ï¸", "🚣ðŸ½â€â™€ï¸", "🚣ðŸ¾â€â™€ï¸", "🚣ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "ðŸŠ", category: 1, name: "person swimming", variations: ["ðŸŠðŸ»", "ðŸŠðŸ¼", "ðŸŠðŸ½", "ðŸŠðŸ¾", "ðŸŠðŸ¿"], version: "1.0" }, { emoji: "ðŸŠâ€â™‚ï¸", category: 1, name: "man swimming", variations: ["ðŸŠðŸ»â€â™‚ï¸", "ðŸŠðŸ¼â€â™‚ï¸", "ðŸŠðŸ½â€â™‚ï¸", "ðŸŠðŸ¾â€â™‚ï¸", "ðŸŠðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "ðŸŠâ€â™€ï¸", category: 1, name: "woman swimming", variations: ["ðŸŠðŸ»â€â™€ï¸", "ðŸŠðŸ¼â€â™€ï¸", "ðŸŠðŸ½â€â™€ï¸", "ðŸŠðŸ¾â€â™€ï¸", "ðŸŠðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "⛹ï¸", category: 1, name: "person bouncing ball", variations: ["⛹ðŸ»", "⛹ðŸ¼", "⛹ðŸ½", "⛹ðŸ¾", "⛹ðŸ¿"], version: "1.0" }, { emoji: "⛹ï¸â€â™‚ï¸", category: 1, name: "man bouncing ball", variations: ["⛹ðŸ»â€â™‚ï¸", "⛹ðŸ¼â€â™‚ï¸", "⛹ðŸ½â€â™‚ï¸", "⛹ðŸ¾â€â™‚ï¸", "⛹ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "⛹ï¸â€â™€ï¸", category: 1, name: "woman bouncing ball", variations: ["⛹ðŸ»â€â™€ï¸", "⛹ðŸ¼â€â™€ï¸", "⛹ðŸ½â€â™€ï¸", "⛹ðŸ¾â€â™€ï¸", "⛹ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "ðŸ‹ï¸", category: 1, name: "person lifting weights", variations: ["ðŸ‹ðŸ»", "ðŸ‹ðŸ¼", "ðŸ‹ðŸ½", "ðŸ‹ðŸ¾", "ðŸ‹ðŸ¿"], version: "1.0" }, { emoji: "ðŸ‹ï¸â€â™‚ï¸", category: 1, name: "man lifting weights", variations: ["ðŸ‹ðŸ»â€â™‚ï¸", "ðŸ‹ðŸ¼â€â™‚ï¸", "ðŸ‹ðŸ½â€â™‚ï¸", "ðŸ‹ðŸ¾â€â™‚ï¸", "ðŸ‹ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "ðŸ‹ï¸â€â™€ï¸", category: 1, name: "woman lifting weights", variations: ["ðŸ‹ðŸ»â€â™€ï¸", "ðŸ‹ðŸ¼â€â™€ï¸", "ðŸ‹ðŸ½â€â™€ï¸", "ðŸ‹ðŸ¾â€â™€ï¸", "ðŸ‹ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "🚴", category: 1, name: "person biking", variations: ["🚴ðŸ»", "🚴ðŸ¼", "🚴ðŸ½", "🚴ðŸ¾", "🚴ðŸ¿"], version: "1.0" }, { emoji: "🚴â€â™‚ï¸", category: 1, name: "man biking", variations: ["🚴ðŸ»â€â™‚ï¸", "🚴ðŸ¼â€â™‚ï¸", "🚴ðŸ½â€â™‚ï¸", "🚴ðŸ¾â€â™‚ï¸", "🚴ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "🚴â€â™€ï¸", category: 1, name: "woman biking", variations: ["🚴ðŸ»â€â™€ï¸", "🚴ðŸ¼â€â™€ï¸", "🚴ðŸ½â€â™€ï¸", "🚴ðŸ¾â€â™€ï¸", "🚴ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "🚵", category: 1, name: "person mountain biking", variations: ["🚵ðŸ»", "🚵ðŸ¼", "🚵ðŸ½", "🚵ðŸ¾", "🚵ðŸ¿"], version: "1.0" }, { emoji: "🚵â€â™‚ï¸", category: 1, name: "man mountain biking", variations: ["🚵ðŸ»â€â™‚ï¸", "🚵ðŸ¼â€â™‚ï¸", "🚵ðŸ½â€â™‚ï¸", "🚵ðŸ¾â€â™‚ï¸", "🚵ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "🚵â€â™€ï¸", category: 1, name: "woman mountain biking", variations: ["🚵ðŸ»â€â™€ï¸", "🚵ðŸ¼â€â™€ï¸", "🚵ðŸ½â€â™€ï¸", "🚵ðŸ¾â€â™€ï¸", "🚵ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "🤸", category: 1, name: "person cartwheeling", variations: ["🤸ðŸ»", "🤸ðŸ¼", "🤸ðŸ½", "🤸ðŸ¾", "🤸ðŸ¿"], version: "3.0" }, { emoji: "🤸â€â™‚ï¸", category: 1, name: "man cartwheeling", variations: ["🤸ðŸ»â€â™‚ï¸", "🤸ðŸ¼â€â™‚ï¸", "🤸ðŸ½â€â™‚ï¸", "🤸ðŸ¾â€â™‚ï¸", "🤸ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "🤸â€â™€ï¸", category: 1, name: "woman cartwheeling", variations: ["🤸ðŸ»â€â™€ï¸", "🤸ðŸ¼â€â™€ï¸", "🤸ðŸ½â€â™€ï¸", "🤸ðŸ¾â€â™€ï¸", "🤸ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "🤼", category: 1, name: "people wrestling", version: "3.0" }, { emoji: "🤼â€â™‚ï¸", category: 1, name: "men wrestling", version: "4.0" }, { emoji: "🤼â€â™€ï¸", category: 1, name: "women wrestling", version: "4.0" }, { emoji: "🤽", category: 1, name: "person playing water polo", variations: ["🤽ðŸ»", "🤽ðŸ¼", "🤽ðŸ½", "🤽ðŸ¾", "🤽ðŸ¿"], version: "3.0" }, { emoji: "🤽â€â™‚ï¸", category: 1, name: "man playing water polo", variations: ["🤽ðŸ»â€â™‚ï¸", "🤽ðŸ¼â€â™‚ï¸", "🤽ðŸ½â€â™‚ï¸", "🤽ðŸ¾â€â™‚ï¸", "🤽ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "🤽â€â™€ï¸", category: 1, name: "woman playing water polo", variations: ["🤽ðŸ»â€â™€ï¸", "🤽ðŸ¼â€â™€ï¸", "🤽ðŸ½â€â™€ï¸", "🤽ðŸ¾â€â™€ï¸", "🤽ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "🤾", category: 1, name: "person playing handball", variations: ["🤾ðŸ»", "🤾ðŸ¼", "🤾ðŸ½", "🤾ðŸ¾", "🤾ðŸ¿"], version: "3.0" }, { emoji: "🤾â€â™‚ï¸", category: 1, name: "man playing handball", variations: ["🤾ðŸ»â€â™‚ï¸", "🤾ðŸ¼â€â™‚ï¸", "🤾ðŸ½â€â™‚ï¸", "🤾ðŸ¾â€â™‚ï¸", "🤾ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "🤾â€â™€ï¸", category: 1, name: "woman playing handball", variations: ["🤾ðŸ»â€â™€ï¸", "🤾ðŸ¼â€â™€ï¸", "🤾ðŸ½â€â™€ï¸", "🤾ðŸ¾â€â™€ï¸", "🤾ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "🤹", category: 1, name: "person juggling", variations: ["🤹ðŸ»", "🤹ðŸ¼", "🤹ðŸ½", "🤹ðŸ¾", "🤹ðŸ¿"], version: "3.0" }, { emoji: "🤹â€â™‚ï¸", category: 1, name: "man juggling", variations: ["🤹ðŸ»â€â™‚ï¸", "🤹ðŸ¼â€â™‚ï¸", "🤹ðŸ½â€â™‚ï¸", "🤹ðŸ¾â€â™‚ï¸", "🤹ðŸ¿â€â™‚ï¸"], version: "4.0" }, { emoji: "🤹â€â™€ï¸", category: 1, name: "woman juggling", variations: ["🤹ðŸ»â€â™€ï¸", "🤹ðŸ¼â€â™€ï¸", "🤹ðŸ½â€â™€ï¸", "🤹ðŸ¾â€â™€ï¸", "🤹ðŸ¿â€â™€ï¸"], version: "4.0" }, { emoji: "🧘", category: 1, name: "person in lotus position", variations: ["🧘ðŸ»", "🧘ðŸ¼", "🧘ðŸ½", "🧘ðŸ¾", "🧘ðŸ¿"], version: "5.0" }, { emoji: "🧘â€â™‚ï¸", category: 1, name: "man in lotus position", variations: ["🧘ðŸ»â€â™‚ï¸", "🧘ðŸ¼â€â™‚ï¸", "🧘ðŸ½â€â™‚ï¸", "🧘ðŸ¾â€â™‚ï¸", "🧘ðŸ¿â€â™‚ï¸"], version: "5.0" }, { emoji: "🧘â€â™€ï¸", category: 1, name: "woman in lotus position", variations: ["🧘ðŸ»â€â™€ï¸", "🧘ðŸ¼â€â™€ï¸", "🧘ðŸ½â€â™€ï¸", "🧘ðŸ¾â€â™€ï¸", "🧘ðŸ¿â€â™€ï¸"], version: "5.0" }, { emoji: "🛀", category: 1, name: "person taking bath", variations: ["🛀ðŸ»", "🛀ðŸ¼", "🛀ðŸ½", "🛀ðŸ¾", "🛀ðŸ¿"], version: "1.0" }, { emoji: "🛌", category: 1, name: "person in bed", variations: ["🛌ðŸ»", "🛌ðŸ¼", "🛌ðŸ½", "🛌ðŸ¾", "🛌ðŸ¿"], version: "1.0" }, { emoji: "🧑â€ðŸ¤â€ðŸ§‘", category: 1, name: "people holding hands", variations: ["🧑ðŸ»â€ðŸ¤â€ðŸ§‘ðŸ»", "🧑ðŸ»â€ðŸ¤â€ðŸ§‘ðŸ¼", "🧑ðŸ»â€ðŸ¤â€ðŸ§‘ðŸ½", "🧑ðŸ»â€ðŸ¤â€ðŸ§‘ðŸ¾", "🧑ðŸ»â€ðŸ¤â€ðŸ§‘ðŸ¿", "🧑ðŸ¼â€ðŸ¤â€ðŸ§‘ðŸ»", "🧑ðŸ¼â€ðŸ¤â€ðŸ§‘ðŸ¼", "🧑ðŸ¼â€ðŸ¤â€ðŸ§‘ðŸ½", "🧑ðŸ¼â€ðŸ¤â€ðŸ§‘ðŸ¾", "🧑ðŸ¼â€ðŸ¤â€ðŸ§‘ðŸ¿", "🧑ðŸ½â€ðŸ¤â€ðŸ§‘ðŸ»", "🧑ðŸ½â€ðŸ¤â€ðŸ§‘ðŸ¼", "🧑ðŸ½â€ðŸ¤â€ðŸ§‘ðŸ½", "🧑ðŸ½â€ðŸ¤â€ðŸ§‘ðŸ¾", "🧑ðŸ½â€ðŸ¤â€ðŸ§‘ðŸ¿", "🧑ðŸ¾â€ðŸ¤â€ðŸ§‘ðŸ»", "🧑ðŸ¾â€ðŸ¤â€ðŸ§‘ðŸ¼", "🧑ðŸ¾â€ðŸ¤â€ðŸ§‘ðŸ½", "🧑ðŸ¾â€ðŸ¤â€ðŸ§‘ðŸ¾", "🧑ðŸ¾â€ðŸ¤â€ðŸ§‘ðŸ¿", "🧑ðŸ¿â€ðŸ¤â€ðŸ§‘ðŸ»", "🧑ðŸ¿â€ðŸ¤â€ðŸ§‘ðŸ¼", "🧑ðŸ¿â€ðŸ¤â€ðŸ§‘ðŸ½", "🧑ðŸ¿â€ðŸ¤â€ðŸ§‘ðŸ¾", "🧑ðŸ¿â€ðŸ¤â€ðŸ§‘ðŸ¿"], version: "12.0" }, { emoji: "ðŸ‘", category: 1, name: "women holding hands", variations: ["ðŸ‘ðŸ»", "👩ðŸ»â€ðŸ¤â€ðŸ‘©ðŸ¼", "👩ðŸ»â€ðŸ¤â€ðŸ‘©ðŸ½", "👩ðŸ»â€ðŸ¤â€ðŸ‘©ðŸ¾", "👩ðŸ»â€ðŸ¤â€ðŸ‘©ðŸ¿", "👩ðŸ¼â€ðŸ¤â€ðŸ‘©ðŸ»", "ðŸ‘ðŸ¼", "👩ðŸ¼â€ðŸ¤â€ðŸ‘©ðŸ½", "👩ðŸ¼â€ðŸ¤â€ðŸ‘©ðŸ¾", "👩ðŸ¼â€ðŸ¤â€ðŸ‘©ðŸ¿", "👩ðŸ½â€ðŸ¤â€ðŸ‘©ðŸ»", "👩ðŸ½â€ðŸ¤â€ðŸ‘©ðŸ¼", "ðŸ‘ðŸ½", "👩ðŸ½â€ðŸ¤â€ðŸ‘©ðŸ¾", "👩ðŸ½â€ðŸ¤â€ðŸ‘©ðŸ¿", "👩ðŸ¾â€ðŸ¤â€ðŸ‘©ðŸ»", "👩ðŸ¾â€ðŸ¤â€ðŸ‘©ðŸ¼", "👩ðŸ¾â€ðŸ¤â€ðŸ‘©ðŸ½", "ðŸ‘ðŸ¾", "👩ðŸ¾â€ðŸ¤â€ðŸ‘©ðŸ¿", "👩ðŸ¿â€ðŸ¤â€ðŸ‘©ðŸ»", "👩ðŸ¿â€ðŸ¤â€ðŸ‘©ðŸ¼", "👩ðŸ¿â€ðŸ¤â€ðŸ‘©ðŸ½", "👩ðŸ¿â€ðŸ¤â€ðŸ‘©ðŸ¾", "ðŸ‘ðŸ¿"], version: "1.0" }, { emoji: "👫", category: 1, name: "woman and man holding hands", variations: ["👫ðŸ»", "👩ðŸ»â€ðŸ¤â€ðŸ‘¨ðŸ¼", "👩ðŸ»â€ðŸ¤â€ðŸ‘¨ðŸ½", "👩ðŸ»â€ðŸ¤â€ðŸ‘¨ðŸ¾", "👩ðŸ»â€ðŸ¤â€ðŸ‘¨ðŸ¿", "👩ðŸ¼â€ðŸ¤â€ðŸ‘¨ðŸ»", "👫ðŸ¼", "👩ðŸ¼â€ðŸ¤â€ðŸ‘¨ðŸ½", "👩ðŸ¼â€ðŸ¤â€ðŸ‘¨ðŸ¾", "👩ðŸ¼â€ðŸ¤â€ðŸ‘¨ðŸ¿", "👩ðŸ½â€ðŸ¤â€ðŸ‘¨ðŸ»", "👩ðŸ½â€ðŸ¤â€ðŸ‘¨ðŸ¼", "👫ðŸ½", "👩ðŸ½â€ðŸ¤â€ðŸ‘¨ðŸ¾", "👩ðŸ½â€ðŸ¤â€ðŸ‘¨ðŸ¿", "👩ðŸ¾â€ðŸ¤â€ðŸ‘¨ðŸ»", "👩ðŸ¾â€ðŸ¤â€ðŸ‘¨ðŸ¼", "👩ðŸ¾â€ðŸ¤â€ðŸ‘¨ðŸ½", "👫ðŸ¾", "👩ðŸ¾â€ðŸ¤â€ðŸ‘¨ðŸ¿", "👩ðŸ¿â€ðŸ¤â€ðŸ‘¨ðŸ»", "👩ðŸ¿â€ðŸ¤â€ðŸ‘¨ðŸ¼", "👩ðŸ¿â€ðŸ¤â€ðŸ‘¨ðŸ½", "👩ðŸ¿â€ðŸ¤â€ðŸ‘¨ðŸ¾", "👫ðŸ¿"], version: "1.0" }, { emoji: "👬", category: 1, name: "men holding hands", variations: ["👬ðŸ»", "👨ðŸ»â€ðŸ¤â€ðŸ‘¨ðŸ¼", "👨ðŸ»â€ðŸ¤â€ðŸ‘¨ðŸ½", "👨ðŸ»â€ðŸ¤â€ðŸ‘¨ðŸ¾", "👨ðŸ»â€ðŸ¤â€ðŸ‘¨ðŸ¿", "👨ðŸ¼â€ðŸ¤â€ðŸ‘¨ðŸ»", "👬ðŸ¼", "👨ðŸ¼â€ðŸ¤â€ðŸ‘¨ðŸ½", "👨ðŸ¼â€ðŸ¤â€ðŸ‘¨ðŸ¾", "👨ðŸ¼â€ðŸ¤â€ðŸ‘¨ðŸ¿", "👨ðŸ½â€ðŸ¤â€ðŸ‘¨ðŸ»", "👨ðŸ½â€ðŸ¤â€ðŸ‘¨ðŸ¼", "👬ðŸ½", "👨ðŸ½â€ðŸ¤â€ðŸ‘¨ðŸ¾", "👨ðŸ½â€ðŸ¤â€ðŸ‘¨ðŸ¿", "👨ðŸ¾â€ðŸ¤â€ðŸ‘¨ðŸ»", "👨ðŸ¾â€ðŸ¤â€ðŸ‘¨ðŸ¼", "👨ðŸ¾â€ðŸ¤â€ðŸ‘¨ðŸ½", "👬ðŸ¾", "👨ðŸ¾â€ðŸ¤â€ðŸ‘¨ðŸ¿", "👨ðŸ¿â€ðŸ¤â€ðŸ‘¨ðŸ»", "👨ðŸ¿â€ðŸ¤â€ðŸ‘¨ðŸ¼", "👨ðŸ¿â€ðŸ¤â€ðŸ‘¨ðŸ½", "👨ðŸ¿â€ðŸ¤â€ðŸ‘¨ðŸ¾", "👬ðŸ¿"], version: "1.0" }, { emoji: "ðŸ’", category: 1, name: "kiss", variations: ["👩â€â¤ï¸â€ðŸ’‹â€ðŸ‘¨", "👨â€â¤ï¸â€ðŸ’‹â€ðŸ‘¨", "👩â€â¤ï¸â€ðŸ’‹â€ðŸ‘©"], version: "1.0" }, { emoji: "💑", category: 1, name: "couple with heart", variations: ["👩â€â¤ï¸â€ðŸ‘¨", "👨â€â¤ï¸â€ðŸ‘¨", "👩â€â¤ï¸â€ðŸ‘©"], version: "1.0" }, { emoji: "👪", category: 1, name: "family", version: "1.0" }, { emoji: "👨â€ðŸ‘©â€ðŸ‘¦", category: 1, name: "family: man, woman, boy", version: "2.0" }, { emoji: "👨â€ðŸ‘©â€ðŸ‘§", category: 1, name: "family: man, woman, girl", version: "2.0" }, { emoji: "👨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦", category: 1, name: "family: man, woman, girl, boy", version: "2.0" }, { emoji: "👨â€ðŸ‘©â€ðŸ‘¦â€ðŸ‘¦", category: 1, name: "family: man, woman, boy, boy", version: "2.0" }, { emoji: "👨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘§", category: 1, name: "family: man, woman, girl, girl", version: "2.0" }, { emoji: "👨â€ðŸ‘¨â€ðŸ‘¦", category: 1, name: "family: man, man, boy", version: "2.0" }, { emoji: "👨â€ðŸ‘¨â€ðŸ‘§", category: 1, name: "family: man, man, girl", version: "2.0" }, { emoji: "👨â€ðŸ‘¨â€ðŸ‘§â€ðŸ‘¦", category: 1, name: "family: man, man, girl, boy", version: "2.0" }, { emoji: "👨â€ðŸ‘¨â€ðŸ‘¦â€ðŸ‘¦", category: 1, name: "family: man, man, boy, boy", version: "2.0" }, { emoji: "👨â€ðŸ‘¨â€ðŸ‘§â€ðŸ‘§", category: 1, name: "family: man, man, girl, girl", version: "2.0" }, { emoji: "👩â€ðŸ‘©â€ðŸ‘¦", category: 1, name: "family: woman, woman, boy", version: "2.0" }, { emoji: "👩â€ðŸ‘©â€ðŸ‘§", category: 1, name: "family: woman, woman, girl", version: "2.0" }, { emoji: "👩â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦", category: 1, name: "family: woman, woman, girl, boy", version: "2.0" }, { emoji: "👩â€ðŸ‘©â€ðŸ‘¦â€ðŸ‘¦", category: 1, name: "family: woman, woman, boy, boy", version: "2.0" }, { emoji: "👩â€ðŸ‘©â€ðŸ‘§â€ðŸ‘§", category: 1, name: "family: woman, woman, girl, girl", version: "2.0" }, { emoji: "👨â€ðŸ‘¦", category: 1, name: "family: man, boy", version: "4.0" }, { emoji: "👨â€ðŸ‘¦â€ðŸ‘¦", category: 1, name: "family: man, boy, boy", version: "4.0" }, { emoji: "👨â€ðŸ‘§", category: 1, name: "family: man, girl", version: "4.0" }, { emoji: "👨â€ðŸ‘§â€ðŸ‘¦", category: 1, name: "family: man, girl, boy", version: "4.0" }, { emoji: "👨â€ðŸ‘§â€ðŸ‘§", category: 1, name: "family: man, girl, girl", version: "4.0" }, { emoji: "👩â€ðŸ‘¦", category: 1, name: "family: woman, boy", version: "4.0" }, { emoji: "👩â€ðŸ‘¦â€ðŸ‘¦", category: 1, name: "family: woman, boy, boy", version: "4.0" }, { emoji: "👩â€ðŸ‘§", category: 1, name: "family: woman, girl", version: "4.0" }, { emoji: "👩â€ðŸ‘§â€ðŸ‘¦", category: 1, name: "family: woman, girl, boy", version: "4.0" }, { emoji: "👩â€ðŸ‘§â€ðŸ‘§", category: 1, name: "family: woman, girl, girl", version: "4.0" }, { emoji: "🗣ï¸", category: 1, name: "speaking head", version: "1.0" }, { emoji: "👤", category: 1, name: "bust in silhouette", version: "1.0" }, { emoji: "👥", category: 1, name: "busts in silhouette", version: "1.0" }, { emoji: "🫂", category: 1, name: "people hugging", version: "13.0" }, { emoji: "👣", category: 1, name: "footprints", version: "1.0" }, { emoji: "ðŸµ", category: 2, name: "monkey face", version: "1.0" }, { emoji: "ðŸ’", category: 2, name: "monkey", version: "1.0" }, { emoji: "ðŸ¦", category: 2, name: "gorilla", version: "3.0" }, { emoji: "🦧", category: 2, name: "orangutan", version: "12.0" }, { emoji: "ðŸ¶", category: 2, name: "dog face", version: "1.0" }, { emoji: "ðŸ•", category: 2, name: "dog", version: "1.0" }, { emoji: "🦮", category: 2, name: "guide dog", version: "12.0" }, { emoji: "ðŸ•â€ðŸ¦º", category: 2, name: "service dog", version: "12.0" }, { emoji: "ðŸ©", category: 2, name: "poodle", version: "1.0" }, { emoji: "ðŸº", category: 2, name: "wolf", version: "1.0" }, { emoji: "🦊", category: 2, name: "fox", version: "3.0" }, { emoji: "ðŸ¦", category: 2, name: "raccoon", version: "11.0" }, { emoji: "ðŸ±", category: 2, name: "cat face", version: "1.0" }, { emoji: "ðŸˆ", category: 2, name: "cat", version: "1.0" }, { emoji: "ðŸˆâ€â¬›", category: 2, name: "black cat", version: "13.0" }, { emoji: "ðŸ¦", category: 2, name: "lion", version: "1.0" }, { emoji: "ðŸ¯", category: 2, name: "tiger face", version: "1.0" }, { emoji: "ðŸ…", category: 2, name: "tiger", version: "1.0" }, { emoji: "ðŸ†", category: 2, name: "leopard", version: "1.0" }, { emoji: "ðŸ´", category: 2, name: "horse face", version: "1.0" }, { emoji: "ðŸŽ", category: 2, name: "horse", version: "1.0" }, { emoji: "🦄", category: 2, name: "unicorn", version: "1.0" }, { emoji: "🦓", category: 2, name: "zebra", version: "5.0" }, { emoji: "🦌", category: 2, name: "deer", version: "3.0" }, { emoji: "🦬", category: 2, name: "bison", version: "13.0" }, { emoji: "ðŸ®", category: 2, name: "cow face", version: "1.0" }, { emoji: "ðŸ‚", category: 2, name: "ox", version: "1.0" }, { emoji: "ðŸƒ", category: 2, name: "water buffalo", version: "1.0" }, { emoji: "ðŸ„", category: 2, name: "cow", version: "1.0" }, { emoji: "ðŸ·", category: 2, name: "pig face", version: "1.0" }, { emoji: "ðŸ–", category: 2, name: "pig", version: "1.0" }, { emoji: "ðŸ—", category: 2, name: "boar", version: "1.0" }, { emoji: "ðŸ½", category: 2, name: "pig nose", version: "1.0" }, { emoji: "ðŸ", category: 2, name: "ram", version: "1.0" }, { emoji: "ðŸ‘", category: 2, name: "ewe", version: "1.0" }, { emoji: "ðŸ", category: 2, name: "goat", version: "1.0" }, { emoji: "ðŸª", category: 2, name: "camel", version: "1.0" }, { emoji: "ðŸ«", category: 2, name: "two-hump camel", version: "1.0" }, { emoji: "🦙", category: 2, name: "llama", version: "11.0" }, { emoji: "🦒", category: 2, name: "giraffe", version: "5.0" }, { emoji: "ðŸ˜", category: 2, name: "elephant", version: "1.0" }, { emoji: "🦣", category: 2, name: "mammoth", version: "13.0" }, { emoji: "ðŸ¦", category: 2, name: "rhinoceros", version: "3.0" }, { emoji: "🦛", category: 2, name: "hippopotamus", version: "11.0" }, { emoji: "ðŸ", category: 2, name: "mouse face", version: "1.0" }, { emoji: "ðŸ", category: 2, name: "mouse", version: "1.0" }, { emoji: "ðŸ€", category: 2, name: "rat", version: "1.0" }, { emoji: "ðŸ¹", category: 2, name: "hamster", version: "1.0" }, { emoji: "ðŸ°", category: 2, name: "rabbit face", version: "1.0" }, { emoji: "ðŸ‡", category: 2, name: "rabbit", version: "1.0" }, { emoji: "ðŸ¿ï¸", category: 2, name: "chipmunk", version: "1.0" }, { emoji: "🦫", category: 2, name: "beaver", version: "13.0" }, { emoji: "🦔", category: 2, name: "hedgehog", version: "5.0" }, { emoji: "🦇", category: 2, name: "bat", version: "3.0" }, { emoji: "ðŸ»", category: 2, name: "bear", version: "1.0" }, { emoji: "ðŸ»â€â„ï¸", category: 2, name: "polar bear", version: "13.0" }, { emoji: "ðŸ¨", category: 2, name: "koala", version: "1.0" }, { emoji: "ðŸ¼", category: 2, name: "panda", version: "1.0" }, { emoji: "🦥", category: 2, name: "sloth", version: "12.0" }, { emoji: "🦦", category: 2, name: "otter", version: "12.0" }, { emoji: "🦨", category: 2, name: "skunk", version: "12.0" }, { emoji: "🦘", category: 2, name: "kangaroo", version: "11.0" }, { emoji: "🦡", category: 2, name: "badger", version: "11.0" }, { emoji: "ðŸ¾", category: 2, name: "paw prints", version: "1.0" }, { emoji: "🦃", category: 2, name: "turkey", version: "1.0" }, { emoji: "ðŸ”", category: 2, name: "chicken", version: "1.0" }, { emoji: "ðŸ“", category: 2, name: "rooster", version: "1.0" }, { emoji: "ðŸ£", category: 2, name: "hatching chick", version: "1.0" }, { emoji: "ðŸ¤", category: 2, name: "baby chick", version: "1.0" }, { emoji: "ðŸ¥", category: 2, name: "front-facing baby chick", version: "1.0" }, { emoji: "ðŸ¦", category: 2, name: "bird", version: "1.0" }, { emoji: "ðŸ§", category: 2, name: "penguin", version: "1.0" }, { emoji: "🕊ï¸", category: 2, name: "dove", version: "1.0" }, { emoji: "🦅", category: 2, name: "eagle", version: "3.0" }, { emoji: "🦆", category: 2, name: "duck", version: "3.0" }, { emoji: "🦢", category: 2, name: "swan", version: "11.0" }, { emoji: "🦉", category: 2, name: "owl", version: "3.0" }, { emoji: "🦤", category: 2, name: "dodo", version: "13.0" }, { emoji: "🪶", category: 2, name: "feather", version: "13.0" }, { emoji: "🦩", category: 2, name: "flamingo", version: "12.0" }, { emoji: "🦚", category: 2, name: "peacock", version: "11.0" }, { emoji: "🦜", category: 2, name: "parrot", version: "11.0" }, { emoji: "ðŸ¸", category: 2, name: "frog", version: "1.0" }, { emoji: "ðŸŠ", category: 2, name: "crocodile", version: "1.0" }, { emoji: "ðŸ¢", category: 2, name: "turtle", version: "1.0" }, { emoji: "🦎", category: 2, name: "lizard", version: "3.0" }, { emoji: "ðŸ", category: 2, name: "snake", version: "1.0" }, { emoji: "ðŸ²", category: 2, name: "dragon face", version: "1.0" }, { emoji: "ðŸ‰", category: 2, name: "dragon", version: "1.0" }, { emoji: "🦕", category: 2, name: "sauropod", version: "5.0" }, { emoji: "🦖", category: 2, name: "T-Rex", version: "5.0" }, { emoji: "ðŸ³", category: 2, name: "spouting whale", version: "1.0" }, { emoji: "ðŸ‹", category: 2, name: "whale", version: "1.0" }, { emoji: "ðŸ¬", category: 2, name: "dolphin", version: "1.0" }, { emoji: "ðŸ¦", category: 2, name: "seal", version: "13.0" }, { emoji: "ðŸŸ", category: 2, name: "fish", version: "1.0" }, { emoji: "ðŸ ", category: 2, name: "tropical fish", version: "1.0" }, { emoji: "ðŸ¡", category: 2, name: "blowfish", version: "1.0" }, { emoji: "🦈", category: 2, name: "shark", version: "3.0" }, { emoji: "ðŸ™", category: 2, name: "octopus", version: "1.0" }, { emoji: "ðŸš", category: 2, name: "spiral shell", version: "1.0" }, { emoji: "ðŸŒ", category: 2, name: "snail", version: "1.0" }, { emoji: "🦋", category: 2, name: "butterfly", version: "3.0" }, { emoji: "ðŸ›", category: 2, name: "bug", version: "1.0" }, { emoji: "ðŸœ", category: 2, name: "ant", version: "1.0" }, { emoji: "ðŸ", category: 2, name: "honeybee", version: "1.0" }, { emoji: "🪲", category: 2, name: "beetle", version: "13.0" }, { emoji: "ðŸž", category: 2, name: "lady beetle", version: "1.0" }, { emoji: "🦗", category: 2, name: "cricket", version: "5.0" }, { emoji: "🪳", category: 2, name: "cockroach", version: "13.0" }, { emoji: "🕷ï¸", category: 2, name: "spider", version: "1.0" }, { emoji: "🕸ï¸", category: 2, name: "spider web", version: "1.0" }, { emoji: "🦂", category: 2, name: "scorpion", version: "1.0" }, { emoji: "🦟", category: 2, name: "mosquito", version: "11.0" }, { emoji: "🪰", category: 2, name: "fly", version: "13.0" }, { emoji: "🪱", category: 2, name: "worm", version: "13.0" }, { emoji: "🦠", category: 2, name: "microbe", version: "11.0" }, { emoji: "ðŸ’", category: 2, name: "bouquet", version: "1.0" }, { emoji: "🌸", category: 2, name: "cherry blossom", version: "1.0" }, { emoji: "💮", category: 2, name: "white flower", version: "1.0" }, { emoji: "ðŸµï¸", category: 2, name: "rosette", version: "1.0" }, { emoji: "🌹", category: 2, name: "rose", version: "1.0" }, { emoji: "🥀", category: 2, name: "wilted flower", version: "3.0" }, { emoji: "🌺", category: 2, name: "hibiscus", version: "1.0" }, { emoji: "🌻", category: 2, name: "sunflower", version: "1.0" }, { emoji: "🌼", category: 2, name: "blossom", version: "1.0" }, { emoji: "🌷", category: 2, name: "tulip", version: "1.0" }, { emoji: "🌱", category: 2, name: "seedling", version: "1.0" }, { emoji: "🪴", category: 2, name: "potted plant", version: "13.0" }, { emoji: "🌲", category: 2, name: "evergreen tree", version: "1.0" }, { emoji: "🌳", category: 2, name: "deciduous tree", version: "1.0" }, { emoji: "🌴", category: 2, name: "palm tree", version: "1.0" }, { emoji: "🌵", category: 2, name: "cactus", version: "1.0" }, { emoji: "🌾", category: 2, name: "sheaf of rice", version: "1.0" }, { emoji: "🌿", category: 2, name: "herb", version: "1.0" }, { emoji: "☘ï¸", category: 2, name: "shamrock", version: "1.0" }, { emoji: "ðŸ€", category: 2, name: "four leaf clover", version: "1.0" }, { emoji: "ðŸ", category: 2, name: "maple leaf", version: "1.0" }, { emoji: "ðŸ‚", category: 2, name: "fallen leaf", version: "1.0" }, { emoji: "ðŸƒ", category: 2, name: "leaf fluttering in wind", version: "1.0" }, { emoji: "ðŸ‡", category: 3, name: "grapes", version: "1.0" }, { emoji: "ðŸˆ", category: 3, name: "melon", version: "1.0" }, { emoji: "ðŸ‰", category: 3, name: "watermelon", version: "1.0" }, { emoji: "ðŸŠ", category: 3, name: "tangerine", version: "1.0" }, { emoji: "ðŸ‹", category: 3, name: "lemon", version: "1.0" }, { emoji: "ðŸŒ", category: 3, name: "banana", version: "1.0" }, { emoji: "ðŸ", category: 3, name: "pineapple", version: "1.0" }, { emoji: "ðŸ¥", category: 3, name: "mango", version: "11.0" }, { emoji: "ðŸŽ", category: 3, name: "red apple", version: "1.0" }, { emoji: "ðŸ", category: 3, name: "green apple", version: "1.0" }, { emoji: "ðŸ", category: 3, name: "pear", version: "1.0" }, { emoji: "ðŸ‘", category: 3, name: "peach", version: "1.0" }, { emoji: "ðŸ’", category: 3, name: "cherries", version: "1.0" }, { emoji: "ðŸ“", category: 3, name: "strawberry", version: "1.0" }, { emoji: "ðŸ«", category: 3, name: "blueberries", version: "13.0" }, { emoji: "ðŸ¥", category: 3, name: "kiwi fruit", version: "3.0" }, { emoji: "ðŸ…", category: 3, name: "tomato", version: "1.0" }, { emoji: "🫒", category: 3, name: "olive", version: "13.0" }, { emoji: "🥥", category: 3, name: "coconut", version: "5.0" }, { emoji: "🥑", category: 3, name: "avocado", version: "3.0" }, { emoji: "ðŸ†", category: 3, name: "eggplant", version: "1.0" }, { emoji: "🥔", category: 3, name: "potato", version: "3.0" }, { emoji: "🥕", category: 3, name: "carrot", version: "3.0" }, { emoji: "🌽", category: 3, name: "ear of corn", version: "1.0" }, { emoji: "🌶ï¸", category: 3, name: "hot pepper", version: "1.0" }, { emoji: "🫑", category: 3, name: "bell pepper", version: "13.0" }, { emoji: "🥒", category: 3, name: "cucumber", version: "3.0" }, { emoji: "🥬", category: 3, name: "leafy green", version: "11.0" }, { emoji: "🥦", category: 3, name: "broccoli", version: "5.0" }, { emoji: "🧄", category: 3, name: "garlic", version: "12.0" }, { emoji: "🧅", category: 3, name: "onion", version: "12.0" }, { emoji: "ðŸ„", category: 3, name: "mushroom", version: "1.0" }, { emoji: "🥜", category: 3, name: "peanuts", version: "3.0" }, { emoji: "🌰", category: 3, name: "chestnut", version: "1.0" }, { emoji: "ðŸž", category: 3, name: "bread", version: "1.0" }, { emoji: "ðŸ¥", category: 3, name: "croissant", version: "3.0" }, { emoji: "🥖", category: 3, name: "baguette bread", version: "3.0" }, { emoji: "🫓", category: 3, name: "flatbread", version: "13.0" }, { emoji: "🥨", category: 3, name: "pretzel", version: "5.0" }, { emoji: "🥯", category: 3, name: "bagel", version: "11.0" }, { emoji: "🥞", category: 3, name: "pancakes", version: "3.0" }, { emoji: "🧇", category: 3, name: "waffle", version: "12.0" }, { emoji: "🧀", category: 3, name: "cheese wedge", version: "1.0" }, { emoji: "ðŸ–", category: 3, name: "meat on bone", version: "1.0" }, { emoji: "ðŸ—", category: 3, name: "poultry leg", version: "1.0" }, { emoji: "🥩", category: 3, name: "cut of meat", version: "5.0" }, { emoji: "🥓", category: 3, name: "bacon", version: "3.0" }, { emoji: "ðŸ”", category: 3, name: "hamburger", version: "1.0" }, { emoji: "ðŸŸ", category: 3, name: "french fries", version: "1.0" }, { emoji: "ðŸ•", category: 3, name: "pizza", version: "1.0" }, { emoji: "ðŸŒ", category: 3, name: "hot dog", version: "1.0" }, { emoji: "🥪", category: 3, name: "sandwich", version: "5.0" }, { emoji: "🌮", category: 3, name: "taco", version: "1.0" }, { emoji: "🌯", category: 3, name: "burrito", version: "1.0" }, { emoji: "🫔", category: 3, name: "tamale", version: "13.0" }, { emoji: "🥙", category: 3, name: "stuffed flatbread", version: "3.0" }, { emoji: "🧆", category: 3, name: "falafel", version: "12.0" }, { emoji: "🥚", category: 3, name: "egg", version: "3.0" }, { emoji: "ðŸ³", category: 3, name: "cooking", version: "1.0" }, { emoji: "🥘", category: 3, name: "shallow pan of food", version: "3.0" }, { emoji: "ðŸ²", category: 3, name: "pot of food", version: "1.0" }, { emoji: "🫕", category: 3, name: "fondue", version: "13.0" }, { emoji: "🥣", category: 3, name: "bowl with spoon", version: "5.0" }, { emoji: "🥗", category: 3, name: "green salad", version: "3.0" }, { emoji: "ðŸ¿", category: 3, name: "popcorn", version: "1.0" }, { emoji: "🧈", category: 3, name: "butter", version: "12.0" }, { emoji: "🧂", category: 3, name: "salt", version: "11.0" }, { emoji: "🥫", category: 3, name: "canned food", version: "5.0" }, { emoji: "ðŸ±", category: 3, name: "bento box", version: "1.0" }, { emoji: "ðŸ˜", category: 3, name: "rice cracker", version: "1.0" }, { emoji: "ðŸ™", category: 3, name: "rice ball", version: "1.0" }, { emoji: "ðŸš", category: 3, name: "cooked rice", version: "1.0" }, { emoji: "ðŸ›", category: 3, name: "curry rice", version: "1.0" }, { emoji: "ðŸœ", category: 3, name: "steaming bowl", version: "1.0" }, { emoji: "ðŸ", category: 3, name: "spaghetti", version: "1.0" }, { emoji: "ðŸ ", category: 3, name: "roasted sweet potato", version: "1.0" }, { emoji: "ðŸ¢", category: 3, name: "oden", version: "1.0" }, { emoji: "ðŸ£", category: 3, name: "sushi", version: "1.0" }, { emoji: "ðŸ¤", category: 3, name: "fried shrimp", version: "1.0" }, { emoji: "ðŸ¥", category: 3, name: "fish cake with swirl", version: "1.0" }, { emoji: "🥮", category: 3, name: "moon cake", version: "11.0" }, { emoji: "ðŸ¡", category: 3, name: "dango", version: "1.0" }, { emoji: "🥟", category: 3, name: "dumpling", version: "5.0" }, { emoji: "🥠", category: 3, name: "fortune cookie", version: "5.0" }, { emoji: "🥡", category: 3, name: "takeout box", version: "5.0" }, { emoji: "🦀", category: 3, name: "crab", version: "1.0" }, { emoji: "🦞", category: 3, name: "lobster", version: "11.0" }, { emoji: "ðŸ¦", category: 3, name: "shrimp", version: "3.0" }, { emoji: "🦑", category: 3, name: "squid", version: "3.0" }, { emoji: "🦪", category: 3, name: "oyster", version: "12.0" }, { emoji: "ðŸ¦", category: 3, name: "soft ice cream", version: "1.0" }, { emoji: "ðŸ§", category: 3, name: "shaved ice", version: "1.0" }, { emoji: "ðŸ¨", category: 3, name: "ice cream", version: "1.0" }, { emoji: "ðŸ©", category: 3, name: "doughnut", version: "1.0" }, { emoji: "ðŸª", category: 3, name: "cookie", version: "1.0" }, { emoji: "🎂", category: 3, name: "birthday cake", version: "1.0" }, { emoji: "ðŸ°", category: 3, name: "shortcake", version: "1.0" }, { emoji: "ðŸ§", category: 3, name: "cupcake", version: "11.0" }, { emoji: "🥧", category: 3, name: "pie", version: "5.0" }, { emoji: "ðŸ«", category: 3, name: "chocolate bar", version: "1.0" }, { emoji: "ðŸ¬", category: 3, name: "candy", version: "1.0" }, { emoji: "ðŸ", category: 3, name: "lollipop", version: "1.0" }, { emoji: "ðŸ®", category: 3, name: "custard", version: "1.0" }, { emoji: "ðŸ¯", category: 3, name: "honey pot", version: "1.0" }, { emoji: "ðŸ¼", category: 3, name: "baby bottle", version: "1.0" }, { emoji: "🥛", category: 3, name: "glass of milk", version: "3.0" }, { emoji: "☕", category: 3, name: "hot beverage", version: "1.0" }, { emoji: "🫖", category: 3, name: "teapot", version: "13.0" }, { emoji: "ðŸµ", category: 3, name: "teacup without handle", version: "1.0" }, { emoji: "ðŸ¶", category: 3, name: "sake", version: "1.0" }, { emoji: "ðŸ¾", category: 3, name: "bottle with popping cork", version: "1.0" }, { emoji: "ðŸ·", category: 3, name: "wine glass", version: "1.0" }, { emoji: "ðŸ¸", category: 3, name: "cocktail glass", version: "1.0" }, { emoji: "ðŸ¹", category: 3, name: "tropical drink", version: "1.0" }, { emoji: "ðŸº", category: 3, name: "beer mug", version: "1.0" }, { emoji: "ðŸ»", category: 3, name: "clinking beer mugs", version: "1.0" }, { emoji: "🥂", category: 3, name: "clinking glasses", version: "3.0" }, { emoji: "🥃", category: 3, name: "tumbler glass", version: "3.0" }, { emoji: "🥤", category: 3, name: "cup with straw", version: "5.0" }, { emoji: "🧋", category: 3, name: "bubble tea", version: "13.0" }, { emoji: "🧃", category: 3, name: "beverage box", version: "12.0" }, { emoji: "🧉", category: 3, name: "mate", version: "12.0" }, { emoji: "🧊", category: 3, name: "ice", version: "12.0" }, { emoji: "🥢", category: 3, name: "chopsticks", version: "5.0" }, { emoji: "ðŸ½ï¸", category: 3, name: "fork and knife with plate", version: "1.0" }, { emoji: "ðŸ´", category: 3, name: "fork and knife", version: "1.0" }, { emoji: "🥄", category: 3, name: "spoon", version: "3.0" }, { emoji: "🔪", category: 3, name: "kitchen knife", version: "1.0" }, { emoji: "ðŸº", category: 3, name: "amphora", version: "1.0" }, { emoji: "ðŸŒ", category: 4, name: "globe showing Europe-Africa", version: "1.0" }, { emoji: "🌎", category: 4, name: "globe showing Americas", version: "1.0" }, { emoji: "ðŸŒ", category: 4, name: "globe showing Asia-Australia", version: "1.0" }, { emoji: "ðŸŒ", category: 4, name: "globe with meridians", version: "1.0" }, { emoji: "🗺ï¸", category: 4, name: "world map", version: "1.0" }, { emoji: "🗾", category: 4, name: "map of Japan", version: "1.0" }, { emoji: "ðŸ§", category: 4, name: "compass", version: "11.0" }, { emoji: "ðŸ”ï¸", category: 4, name: "snow-capped mountain", version: "1.0" }, { emoji: "â›°ï¸", category: 4, name: "mountain", version: "1.0" }, { emoji: "🌋", category: 4, name: "volcano", version: "1.0" }, { emoji: "🗻", category: 4, name: "mount fuji", version: "1.0" }, { emoji: "ðŸ•ï¸", category: 4, name: "camping", version: "1.0" }, { emoji: "ðŸ–ï¸", category: 4, name: "beach with umbrella", version: "1.0" }, { emoji: "ðŸœï¸", category: 4, name: "desert", version: "1.0" }, { emoji: "ðŸï¸", category: 4, name: "desert island", version: "1.0" }, { emoji: "ðŸžï¸", category: 4, name: "national park", version: "1.0" }, { emoji: "ðŸŸï¸", category: 4, name: "stadium", version: "1.0" }, { emoji: "ðŸ›ï¸", category: 4, name: "classical building", version: "1.0" }, { emoji: "ðŸ—ï¸", category: 4, name: "building construction", version: "1.0" }, { emoji: "🧱", category: 4, name: "brick", version: "11.0" }, { emoji: "🪨", category: 4, name: "rock", version: "13.0" }, { emoji: "🪵", category: 4, name: "wood", version: "13.0" }, { emoji: "🛖", category: 4, name: "hut", version: "13.0" }, { emoji: "ðŸ˜ï¸", category: 4, name: "houses", version: "1.0" }, { emoji: "ðŸšï¸", category: 4, name: "derelict house", version: "1.0" }, { emoji: "ðŸ ", category: 4, name: "house", version: "1.0" }, { emoji: "ðŸ¡", category: 4, name: "house with garden", version: "1.0" }, { emoji: "ðŸ¢", category: 4, name: "office building", version: "1.0" }, { emoji: "ðŸ£", category: 4, name: "Japanese post office", version: "1.0" }, { emoji: "ðŸ¤", category: 4, name: "post office", version: "1.0" }, { emoji: "ðŸ¥", category: 4, name: "hospital", version: "1.0" }, { emoji: "ðŸ¦", category: 4, name: "bank", version: "1.0" }, { emoji: "ðŸ¨", category: 4, name: "hotel", version: "1.0" }, { emoji: "ðŸ©", category: 4, name: "love hotel", version: "1.0" }, { emoji: "ðŸª", category: 4, name: "convenience store", version: "1.0" }, { emoji: "ðŸ«", category: 4, name: "school", version: "1.0" }, { emoji: "ðŸ¬", category: 4, name: "department store", version: "1.0" }, { emoji: "ðŸ", category: 4, name: "factory", version: "1.0" }, { emoji: "ðŸ¯", category: 4, name: "Japanese castle", version: "1.0" }, { emoji: "ðŸ°", category: 4, name: "castle", version: "1.0" }, { emoji: "💒", category: 4, name: "wedding", version: "1.0" }, { emoji: "🗼", category: 4, name: "Tokyo tower", version: "1.0" }, { emoji: "🗽", category: 4, name: "Statue of Liberty", version: "1.0" }, { emoji: "⛪", category: 4, name: "church", version: "1.0" }, { emoji: "🕌", category: 4, name: "mosque", version: "1.0" }, { emoji: "🛕", category: 4, name: "hindu temple", version: "12.0" }, { emoji: "ðŸ•", category: 4, name: "synagogue", version: "1.0" }, { emoji: "⛩ï¸", category: 4, name: "shinto shrine", version: "1.0" }, { emoji: "🕋", category: 4, name: "kaaba", version: "1.0" }, { emoji: "⛲", category: 4, name: "fountain", version: "1.0" }, { emoji: "⛺", category: 4, name: "tent", version: "1.0" }, { emoji: "ðŸŒ", category: 4, name: "foggy", version: "1.0" }, { emoji: "🌃", category: 4, name: "night with stars", version: "1.0" }, { emoji: "ðŸ™ï¸", category: 4, name: "cityscape", version: "1.0" }, { emoji: "🌄", category: 4, name: "sunrise over mountains", version: "1.0" }, { emoji: "🌅", category: 4, name: "sunrise", version: "1.0" }, { emoji: "🌆", category: 4, name: "cityscape at dusk", version: "1.0" }, { emoji: "🌇", category: 4, name: "sunset", version: "1.0" }, { emoji: "🌉", category: 4, name: "bridge at night", version: "1.0" }, { emoji: "♨ï¸", category: 4, name: "hot springs", version: "1.0" }, { emoji: "🎠", category: 4, name: "carousel horse", version: "1.0" }, { emoji: "🎡", category: 4, name: "ferris wheel", version: "1.0" }, { emoji: "🎢", category: 4, name: "roller coaster", version: "1.0" }, { emoji: "💈", category: 4, name: "barber pole", version: "1.0" }, { emoji: "🎪", category: 4, name: "circus tent", version: "1.0" }, { emoji: "🚂", category: 4, name: "locomotive", version: "1.0" }, { emoji: "🚃", category: 4, name: "railway car", version: "1.0" }, { emoji: "🚄", category: 4, name: "high-speed train", version: "1.0" }, { emoji: "🚅", category: 4, name: "bullet train", version: "1.0" }, { emoji: "🚆", category: 4, name: "train", version: "1.0" }, { emoji: "🚇", category: 4, name: "metro", version: "1.0" }, { emoji: "🚈", category: 4, name: "light rail", version: "1.0" }, { emoji: "🚉", category: 4, name: "station", version: "1.0" }, { emoji: "🚊", category: 4, name: "tram", version: "1.0" }, { emoji: "ðŸš", category: 4, name: "monorail", version: "1.0" }, { emoji: "🚞", category: 4, name: "mountain railway", version: "1.0" }, { emoji: "🚋", category: 4, name: "tram car", version: "1.0" }, { emoji: "🚌", category: 4, name: "bus", version: "1.0" }, { emoji: "ðŸš", category: 4, name: "oncoming bus", version: "1.0" }, { emoji: "🚎", category: 4, name: "trolleybus", version: "1.0" }, { emoji: "ðŸš", category: 4, name: "minibus", version: "1.0" }, { emoji: "🚑", category: 4, name: "ambulance", version: "1.0" }, { emoji: "🚒", category: 4, name: "fire engine", version: "1.0" }, { emoji: "🚓", category: 4, name: "police car", version: "1.0" }, { emoji: "🚔", category: 4, name: "oncoming police car", version: "1.0" }, { emoji: "🚕", category: 4, name: "taxi", version: "1.0" }, { emoji: "🚖", category: 4, name: "oncoming taxi", version: "1.0" }, { emoji: "🚗", category: 4, name: "automobile", version: "1.0" }, { emoji: "🚘", category: 4, name: "oncoming automobile", version: "1.0" }, { emoji: "🚙", category: 4, name: "sport utility vehicle", version: "1.0" }, { emoji: "🛻", category: 4, name: "pickup truck", version: "13.0" }, { emoji: "🚚", category: 4, name: "delivery truck", version: "1.0" }, { emoji: "🚛", category: 4, name: "articulated lorry", version: "1.0" }, { emoji: "🚜", category: 4, name: "tractor", version: "1.0" }, { emoji: "ðŸŽï¸", category: 4, name: "racing car", version: "1.0" }, { emoji: "ðŸï¸", category: 4, name: "motorcycle", version: "1.0" }, { emoji: "🛵", category: 4, name: "motor scooter", version: "3.0" }, { emoji: "🦽", category: 4, name: "manual wheelchair", version: "12.0" }, { emoji: "🦼", category: 4, name: "motorized wheelchair", version: "12.0" }, { emoji: "🛺", category: 4, name: "auto rickshaw", version: "12.0" }, { emoji: "🚲", category: 4, name: "bicycle", version: "1.0" }, { emoji: "🛴", category: 4, name: "kick scooter", version: "3.0" }, { emoji: "🛹", category: 4, name: "skateboard", version: "11.0" }, { emoji: "🛼", category: 4, name: "roller skate", version: "13.0" }, { emoji: "ðŸš", category: 4, name: "bus stop", version: "1.0" }, { emoji: "🛣ï¸", category: 4, name: "motorway", version: "1.0" }, { emoji: "🛤ï¸", category: 4, name: "railway track", version: "1.0" }, { emoji: "🛢ï¸", category: 4, name: "oil drum", version: "1.0" }, { emoji: "⛽", category: 4, name: "fuel pump", version: "1.0" }, { emoji: "🚨", category: 4, name: "police car light", version: "1.0" }, { emoji: "🚥", category: 4, name: "horizontal traffic light", version: "1.0" }, { emoji: "🚦", category: 4, name: "vertical traffic light", version: "1.0" }, { emoji: "🛑", category: 4, name: "stop sign", version: "3.0" }, { emoji: "🚧", category: 4, name: "construction", version: "1.0" }, { emoji: "âš“", category: 4, name: "anchor", version: "1.0" }, { emoji: "⛵", category: 4, name: "sailboat", version: "1.0" }, { emoji: "🛶", category: 4, name: "canoe", version: "3.0" }, { emoji: "🚤", category: 4, name: "speedboat", version: "1.0" }, { emoji: "🛳ï¸", category: 4, name: "passenger ship", version: "1.0" }, { emoji: "â›´ï¸", category: 4, name: "ferry", version: "1.0" }, { emoji: "🛥ï¸", category: 4, name: "motor boat", version: "1.0" }, { emoji: "🚢", category: 4, name: "ship", version: "1.0" }, { emoji: "✈ï¸", category: 4, name: "airplane", version: "1.0" }, { emoji: "🛩ï¸", category: 4, name: "small airplane", version: "1.0" }, { emoji: "🛫", category: 4, name: "airplane departure", version: "1.0" }, { emoji: "🛬", category: 4, name: "airplane arrival", version: "1.0" }, { emoji: "🪂", category: 4, name: "parachute", version: "12.0" }, { emoji: "💺", category: 4, name: "seat", version: "1.0" }, { emoji: "ðŸš", category: 4, name: "helicopter", version: "1.0" }, { emoji: "🚟", category: 4, name: "suspension railway", version: "1.0" }, { emoji: "🚠", category: 4, name: "mountain cableway", version: "1.0" }, { emoji: "🚡", category: 4, name: "aerial tramway", version: "1.0" }, { emoji: "🛰ï¸", category: 4, name: "satellite", version: "1.0" }, { emoji: "🚀", category: 4, name: "rocket", version: "1.0" }, { emoji: "🛸", category: 4, name: "flying saucer", version: "5.0" }, { emoji: "🛎ï¸", category: 4, name: "bellhop bell", version: "1.0" }, { emoji: "🧳", category: 4, name: "luggage", version: "11.0" }, { emoji: "⌛", category: 4, name: "hourglass done", version: "1.0" }, { emoji: "â³", category: 4, name: "hourglass not done", version: "1.0" }, { emoji: "⌚", category: 4, name: "watch", version: "1.0" }, { emoji: "â°", category: 4, name: "alarm clock", version: "1.0" }, { emoji: "â±ï¸", category: 4, name: "stopwatch", version: "1.0" }, { emoji: "â²ï¸", category: 4, name: "timer clock", version: "1.0" }, { emoji: "🕰ï¸", category: 4, name: "mantelpiece clock", version: "1.0" }, { emoji: "🕛", category: 4, name: "twelve o’clock", version: "1.0" }, { emoji: "🕧", category: 4, name: "twelve-thirty", version: "1.0" }, { emoji: "ðŸ•", category: 4, name: "one o’clock", version: "1.0" }, { emoji: "🕜", category: 4, name: "one-thirty", version: "1.0" }, { emoji: "🕑", category: 4, name: "two o’clock", version: "1.0" }, { emoji: "ðŸ•", category: 4, name: "two-thirty", version: "1.0" }, { emoji: "🕒", category: 4, name: "three o’clock", version: "1.0" }, { emoji: "🕞", category: 4, name: "three-thirty", version: "1.0" }, { emoji: "🕓", category: 4, name: "four o’clock", version: "1.0" }, { emoji: "🕟", category: 4, name: "four-thirty", version: "1.0" }, { emoji: "🕔", category: 4, name: "five o’clock", version: "1.0" }, { emoji: "🕠", category: 4, name: "five-thirty", version: "1.0" }, { emoji: "🕕", category: 4, name: "six o’clock", version: "1.0" }, { emoji: "🕡", category: 4, name: "six-thirty", version: "1.0" }, { emoji: "🕖", category: 4, name: "seven o’clock", version: "1.0" }, { emoji: "🕢", category: 4, name: "seven-thirty", version: "1.0" }, { emoji: "🕗", category: 4, name: "eight o’clock", version: "1.0" }, { emoji: "🕣", category: 4, name: "eight-thirty", version: "1.0" }, { emoji: "🕘", category: 4, name: "nine o’clock", version: "1.0" }, { emoji: "🕤", category: 4, name: "nine-thirty", version: "1.0" }, { emoji: "🕙", category: 4, name: "ten o’clock", version: "1.0" }, { emoji: "🕥", category: 4, name: "ten-thirty", version: "1.0" }, { emoji: "🕚", category: 4, name: "eleven o’clock", version: "1.0" }, { emoji: "🕦", category: 4, name: "eleven-thirty", version: "1.0" }, { emoji: "🌑", category: 4, name: "new moon", version: "1.0" }, { emoji: "🌒", category: 4, name: "waxing crescent moon", version: "1.0" }, { emoji: "🌓", category: 4, name: "first quarter moon", version: "1.0" }, { emoji: "🌔", category: 4, name: "waxing gibbous moon", version: "1.0" }, { emoji: "🌕", category: 4, name: "full moon", version: "1.0" }, { emoji: "🌖", category: 4, name: "waning gibbous moon", version: "1.0" }, { emoji: "🌗", category: 4, name: "last quarter moon", version: "1.0" }, { emoji: "🌘", category: 4, name: "waning crescent moon", version: "1.0" }, { emoji: "🌙", category: 4, name: "crescent moon", version: "1.0" }, { emoji: "🌚", category: 4, name: "new moon face", version: "1.0" }, { emoji: "🌛", category: 4, name: "first quarter moon face", version: "1.0" }, { emoji: "🌜", category: 4, name: "last quarter moon face", version: "1.0" }, { emoji: "🌡ï¸", category: 4, name: "thermometer", version: "1.0" }, { emoji: "☀ï¸", category: 4, name: "sun", version: "1.0" }, { emoji: "ðŸŒ", category: 4, name: "full moon face", version: "1.0" }, { emoji: "🌞", category: 4, name: "sun with face", version: "1.0" }, { emoji: "ðŸª", category: 4, name: "ringed planet", version: "12.0" }, { emoji: "â", category: 4, name: "star", version: "1.0" }, { emoji: "🌟", category: 4, name: "glowing star", version: "1.0" }, { emoji: "🌠", category: 4, name: "shooting star", version: "1.0" }, { emoji: "🌌", category: 4, name: "milky way", version: "1.0" }, { emoji: "â˜ï¸", category: 4, name: "cloud", version: "1.0" }, { emoji: "â›…", category: 4, name: "sun behind cloud", version: "1.0" }, { emoji: "⛈ï¸", category: 4, name: "cloud with lightning and rain", version: "1.0" }, { emoji: "🌤ï¸", category: 4, name: "sun behind small cloud", version: "1.0" }, { emoji: "🌥ï¸", category: 4, name: "sun behind large cloud", version: "1.0" }, { emoji: "🌦ï¸", category: 4, name: "sun behind rain cloud", version: "1.0" }, { emoji: "🌧ï¸", category: 4, name: "cloud with rain", version: "1.0" }, { emoji: "🌨ï¸", category: 4, name: "cloud with snow", version: "1.0" }, { emoji: "🌩ï¸", category: 4, name: "cloud with lightning", version: "1.0" }, { emoji: "🌪ï¸", category: 4, name: "tornado", version: "1.0" }, { emoji: "🌫ï¸", category: 4, name: "fog", version: "1.0" }, { emoji: "🌬ï¸", category: 4, name: "wind face", version: "1.0" }, { emoji: "🌀", category: 4, name: "cyclone", version: "1.0" }, { emoji: "🌈", category: 4, name: "rainbow", version: "1.0" }, { emoji: "🌂", category: 4, name: "closed umbrella", version: "1.0" }, { emoji: "☂ï¸", category: 4, name: "umbrella", version: "1.0" }, { emoji: "☔", category: 4, name: "umbrella with rain drops", version: "1.0" }, { emoji: "â›±ï¸", category: 4, name: "umbrella on ground", version: "1.0" }, { emoji: "âš¡", category: 4, name: "high voltage", version: "1.0" }, { emoji: "â„ï¸", category: 4, name: "snowflake", version: "1.0" }, { emoji: "☃ï¸", category: 4, name: "snowman", version: "1.0" }, { emoji: "⛄", category: 4, name: "snowman without snow", version: "1.0" }, { emoji: "☄ï¸", category: 4, name: "comet", version: "1.0" }, { emoji: "🔥", category: 4, name: "fire", version: "1.0" }, { emoji: "💧", category: 4, name: "droplet", version: "1.0" }, { emoji: "🌊", category: 4, name: "water wave", version: "1.0" }, { emoji: "🎃", category: 5, name: "jack-o-lantern", version: "1.0" }, { emoji: "🎄", category: 5, name: "Christmas tree", version: "1.0" }, { emoji: "🎆", category: 5, name: "fireworks", version: "1.0" }, { emoji: "🎇", category: 5, name: "sparkler", version: "1.0" }, { emoji: "🧨", category: 5, name: "firecracker", version: "11.0" }, { emoji: "✨", category: 5, name: "sparkles", version: "1.0" }, { emoji: "🎈", category: 5, name: "balloon", version: "1.0" }, { emoji: "🎉", category: 5, name: "party popper", version: "1.0" }, { emoji: "🎊", category: 5, name: "confetti ball", version: "1.0" }, { emoji: "🎋", category: 5, name: "tanabata tree", version: "1.0" }, { emoji: "ðŸŽ", category: 5, name: "pine decoration", version: "1.0" }, { emoji: "🎎", category: 5, name: "Japanese dolls", version: "1.0" }, { emoji: "ðŸŽ", category: 5, name: "carp streamer", version: "1.0" }, { emoji: "ðŸŽ", category: 5, name: "wind chime", version: "1.0" }, { emoji: "🎑", category: 5, name: "moon viewing ceremony", version: "1.0" }, { emoji: "🧧", category: 5, name: "red envelope", version: "11.0" }, { emoji: "🎀", category: 5, name: "ribbon", version: "1.0" }, { emoji: "ðŸŽ", category: 5, name: "wrapped gift", version: "1.0" }, { emoji: "🎗ï¸", category: 5, name: "reminder ribbon", version: "1.0" }, { emoji: "🎟ï¸", category: 5, name: "admission tickets", version: "1.0" }, { emoji: "🎫", category: 5, name: "ticket", version: "1.0" }, { emoji: "🎖ï¸", category: 5, name: "military medal", version: "1.0" }, { emoji: "ðŸ†", category: 5, name: "trophy", version: "1.0" }, { emoji: "ðŸ…", category: 5, name: "sports medal", version: "1.0" }, { emoji: "🥇", category: 5, name: "1st place medal", version: "3.0" }, { emoji: "🥈", category: 5, name: "2nd place medal", version: "3.0" }, { emoji: "🥉", category: 5, name: "3rd place medal", version: "3.0" }, { emoji: "âš½", category: 5, name: "soccer ball", version: "1.0" }, { emoji: "âš¾", category: 5, name: "baseball", version: "1.0" }, { emoji: "🥎", category: 5, name: "softball", version: "11.0" }, { emoji: "ðŸ€", category: 5, name: "basketball", version: "1.0" }, { emoji: "ðŸ", category: 5, name: "volleyball", version: "1.0" }, { emoji: "ðŸˆ", category: 5, name: "american football", version: "1.0" }, { emoji: "ðŸ‰", category: 5, name: "rugby football", version: "1.0" }, { emoji: "🎾", category: 5, name: "tennis", version: "1.0" }, { emoji: "ðŸ¥", category: 5, name: "flying disc", version: "11.0" }, { emoji: "🎳", category: 5, name: "bowling", version: "1.0" }, { emoji: "ðŸ", category: 5, name: "cricket game", version: "1.0" }, { emoji: "ðŸ‘", category: 5, name: "field hockey", version: "1.0" }, { emoji: "ðŸ’", category: 5, name: "ice hockey", version: "1.0" }, { emoji: "ðŸ¥", category: 5, name: "lacrosse", version: "11.0" }, { emoji: "ðŸ“", category: 5, name: "ping pong", version: "1.0" }, { emoji: "ðŸ¸", category: 5, name: "badminton", version: "1.0" }, { emoji: "🥊", category: 5, name: "boxing glove", version: "3.0" }, { emoji: "🥋", category: 5, name: "martial arts uniform", version: "3.0" }, { emoji: "🥅", category: 5, name: "goal net", version: "3.0" }, { emoji: "⛳", category: 5, name: "flag in hole", version: "1.0" }, { emoji: "⛸ï¸", category: 5, name: "ice skate", version: "1.0" }, { emoji: "🎣", category: 5, name: "fishing pole", version: "1.0" }, { emoji: "🤿", category: 5, name: "diving mask", version: "12.0" }, { emoji: "🎽", category: 5, name: "running shirt", version: "1.0" }, { emoji: "🎿", category: 5, name: "skis", version: "1.0" }, { emoji: "🛷", category: 5, name: "sled", version: "5.0" }, { emoji: "🥌", category: 5, name: "curling stone", version: "5.0" }, { emoji: "🎯", category: 5, name: "direct hit", version: "1.0" }, { emoji: "🪀", category: 5, name: "yo-yo", version: "12.0" }, { emoji: "ðŸª", category: 5, name: "kite", version: "12.0" }, { emoji: "🎱", category: 5, name: "pool 8 ball", version: "1.0" }, { emoji: "🔮", category: 5, name: "crystal ball", version: "1.0" }, { emoji: "🪄", category: 5, name: "magic wand", version: "13.0" }, { emoji: "🧿", category: 5, name: "nazar amulet", version: "11.0" }, { emoji: "🎮", category: 5, name: "video game", version: "1.0" }, { emoji: "🕹ï¸", category: 5, name: "joystick", version: "1.0" }, { emoji: "🎰", category: 5, name: "slot machine", version: "1.0" }, { emoji: "🎲", category: 5, name: "game die", version: "1.0" }, { emoji: "🧩", category: 5, name: "puzzle piece", version: "11.0" }, { emoji: "🧸", category: 5, name: "teddy bear", version: "11.0" }, { emoji: "🪅", category: 5, name: "piñata", version: "13.0" }, { emoji: "🪆", category: 5, name: "nesting dolls", version: "13.0" }, { emoji: "â™ ï¸", category: 5, name: "spade suit", version: "1.0" }, { emoji: "♥ï¸", category: 5, name: "heart suit", version: "1.0" }, { emoji: "♦ï¸", category: 5, name: "diamond suit", version: "1.0" }, { emoji: "♣ï¸", category: 5, name: "club suit", version: "1.0" }, { emoji: "♟ï¸", category: 5, name: "chess pawn", version: "11.0" }, { emoji: "ðŸƒ", category: 5, name: "joker", version: "1.0" }, { emoji: "🀄", category: 5, name: "mahjong red dragon", version: "1.0" }, { emoji: "🎴", category: 5, name: "flower playing cards", version: "1.0" }, { emoji: "ðŸŽ", category: 5, name: "performing arts", version: "1.0" }, { emoji: "🖼ï¸", category: 5, name: "framed picture", version: "1.0" }, { emoji: "🎨", category: 5, name: "artist palette", version: "1.0" }, { emoji: "🧵", category: 5, name: "thread", version: "11.0" }, { emoji: "🪡", category: 5, name: "sewing needle", version: "13.0" }, { emoji: "🧶", category: 5, name: "yarn", version: "11.0" }, { emoji: "🪢", category: 5, name: "knot", version: "13.0" }, { emoji: "👓", category: 6, name: "glasses", version: "1.0" }, { emoji: "🕶ï¸", category: 6, name: "sunglasses", version: "1.0" }, { emoji: "🥽", category: 6, name: "goggles", version: "11.0" }, { emoji: "🥼", category: 6, name: "lab coat", version: "11.0" }, { emoji: "🦺", category: 6, name: "safety vest", version: "12.0" }, { emoji: "👔", category: 6, name: "necktie", version: "1.0" }, { emoji: "👕", category: 6, name: "t-shirt", version: "1.0" }, { emoji: "👖", category: 6, name: "jeans", version: "1.0" }, { emoji: "🧣", category: 6, name: "scarf", version: "5.0" }, { emoji: "🧤", category: 6, name: "gloves", version: "5.0" }, { emoji: "🧥", category: 6, name: "coat", version: "5.0" }, { emoji: "🧦", category: 6, name: "socks", version: "5.0" }, { emoji: "👗", category: 6, name: "dress", version: "1.0" }, { emoji: "👘", category: 6, name: "kimono", version: "1.0" }, { emoji: "🥻", category: 6, name: "sari", version: "12.0" }, { emoji: "🩱", category: 6, name: "one-piece swimsuit", version: "12.0" }, { emoji: "🩲", category: 6, name: "briefs", version: "12.0" }, { emoji: "🩳", category: 6, name: "shorts", version: "12.0" }, { emoji: "👙", category: 6, name: "bikini", version: "1.0" }, { emoji: "👚", category: 6, name: "woman’s clothes", version: "1.0" }, { emoji: "👛", category: 6, name: "purse", version: "1.0" }, { emoji: "👜", category: 6, name: "handbag", version: "1.0" }, { emoji: "ðŸ‘", category: 6, name: "clutch bag", version: "1.0" }, { emoji: "ðŸ›ï¸", category: 6, name: "shopping bags", version: "1.0" }, { emoji: "🎒", category: 6, name: "backpack", version: "1.0" }, { emoji: "🩴", category: 6, name: "thong sandal", version: "13.0" }, { emoji: "👞", category: 6, name: "man’s shoe", version: "1.0" }, { emoji: "👟", category: 6, name: "running shoe", version: "1.0" }, { emoji: "🥾", category: 6, name: "hiking boot", version: "11.0" }, { emoji: "🥿", category: 6, name: "flat shoe", version: "11.0" }, { emoji: "👠", category: 6, name: "high-heeled shoe", version: "1.0" }, { emoji: "👡", category: 6, name: "woman’s sandal", version: "1.0" }, { emoji: "🩰", category: 6, name: "ballet shoes", version: "12.0" }, { emoji: "👢", category: 6, name: "woman’s boot", version: "1.0" }, { emoji: "👑", category: 6, name: "crown", version: "1.0" }, { emoji: "👒", category: 6, name: "woman’s hat", version: "1.0" }, { emoji: "🎩", category: 6, name: "top hat", version: "1.0" }, { emoji: "🎓", category: 6, name: "graduation cap", version: "1.0" }, { emoji: "🧢", category: 6, name: "billed cap", version: "5.0" }, { emoji: "🪖", category: 6, name: "military helmet", version: "13.0" }, { emoji: "⛑ï¸", category: 6, name: "rescue worker’s helmet", version: "1.0" }, { emoji: "📿", category: 6, name: "prayer beads", version: "1.0" }, { emoji: "💄", category: 6, name: "lipstick", version: "1.0" }, { emoji: "ðŸ’", category: 6, name: "ring", version: "1.0" }, { emoji: "💎", category: 6, name: "gem stone", version: "1.0" }, { emoji: "🔇", category: 6, name: "muted speaker", version: "1.0" }, { emoji: "🔈", category: 6, name: "speaker low volume", version: "1.0" }, { emoji: "🔉", category: 6, name: "speaker medium volume", version: "1.0" }, { emoji: "🔊", category: 6, name: "speaker high volume", version: "1.0" }, { emoji: "📢", category: 6, name: "loudspeaker", version: "1.0" }, { emoji: "📣", category: 6, name: "megaphone", version: "1.0" }, { emoji: "📯", category: 6, name: "postal horn", version: "1.0" }, { emoji: "🔔", category: 6, name: "bell", version: "1.0" }, { emoji: "🔕", category: 6, name: "bell with slash", version: "1.0" }, { emoji: "🎼", category: 6, name: "musical score", version: "1.0" }, { emoji: "🎵", category: 6, name: "musical note", version: "1.0" }, { emoji: "🎶", category: 6, name: "musical notes", version: "1.0" }, { emoji: "🎙ï¸", category: 6, name: "studio microphone", version: "1.0" }, { emoji: "🎚ï¸", category: 6, name: "level slider", version: "1.0" }, { emoji: "🎛ï¸", category: 6, name: "control knobs", version: "1.0" }, { emoji: "🎤", category: 6, name: "microphone", version: "1.0" }, { emoji: "🎧", category: 6, name: "headphone", version: "1.0" }, { emoji: "📻", category: 6, name: "radio", version: "1.0" }, { emoji: "🎷", category: 6, name: "saxophone", version: "1.0" }, { emoji: "🪗", category: 6, name: "accordion", version: "13.0" }, { emoji: "🎸", category: 6, name: "guitar", version: "1.0" }, { emoji: "🎹", category: 6, name: "musical keyboard", version: "1.0" }, { emoji: "🎺", category: 6, name: "trumpet", version: "1.0" }, { emoji: "🎻", category: 6, name: "violin", version: "1.0" }, { emoji: "🪕", category: 6, name: "banjo", version: "12.0" }, { emoji: "ðŸ¥", category: 6, name: "drum", version: "3.0" }, { emoji: "🪘", category: 6, name: "long drum", version: "13.0" }, { emoji: "📱", category: 6, name: "mobile phone", version: "1.0" }, { emoji: "📲", category: 6, name: "mobile phone with arrow", version: "1.0" }, { emoji: "☎ï¸", category: 6, name: "telephone", version: "1.0" }, { emoji: "📞", category: 6, name: "telephone receiver", version: "1.0" }, { emoji: "📟", category: 6, name: "pager", version: "1.0" }, { emoji: "📠", category: 6, name: "fax machine", version: "1.0" }, { emoji: "🔋", category: 6, name: "battery", version: "1.0" }, { emoji: "🔌", category: 6, name: "electric plug", version: "1.0" }, { emoji: "💻", category: 6, name: "laptop", version: "1.0" }, { emoji: "🖥ï¸", category: 6, name: "desktop computer", version: "1.0" }, { emoji: "🖨ï¸", category: 6, name: "printer", version: "1.0" }, { emoji: "⌨ï¸", category: 6, name: "keyboard", version: "1.0" }, { emoji: "🖱ï¸", category: 6, name: "computer mouse", version: "1.0" }, { emoji: "🖲ï¸", category: 6, name: "trackball", version: "1.0" }, { emoji: "💽", category: 6, name: "computer disk", version: "1.0" }, { emoji: "💾", category: 6, name: "floppy disk", version: "1.0" }, { emoji: "💿", category: 6, name: "optical disk", version: "1.0" }, { emoji: "📀", category: 6, name: "dvd", version: "1.0" }, { emoji: "🧮", category: 6, name: "abacus", version: "11.0" }, { emoji: "🎥", category: 6, name: "movie camera", version: "1.0" }, { emoji: "🎞ï¸", category: 6, name: "film frames", version: "1.0" }, { emoji: "📽ï¸", category: 6, name: "film projector", version: "1.0" }, { emoji: "🎬", category: 6, name: "clapper board", version: "1.0" }, { emoji: "📺", category: 6, name: "television", version: "1.0" }, { emoji: "📷", category: 6, name: "camera", version: "1.0" }, { emoji: "📸", category: 6, name: "camera with flash", version: "1.0" }, { emoji: "📹", category: 6, name: "video camera", version: "1.0" }, { emoji: "📼", category: 6, name: "videocassette", version: "1.0" }, { emoji: "ðŸ”", category: 6, name: "magnifying glass tilted left", version: "1.0" }, { emoji: "🔎", category: 6, name: "magnifying glass tilted right", version: "1.0" }, { emoji: "🕯ï¸", category: 6, name: "candle", version: "1.0" }, { emoji: "💡", category: 6, name: "light bulb", version: "1.0" }, { emoji: "🔦", category: 6, name: "flashlight", version: "1.0" }, { emoji: "ðŸ®", category: 6, name: "red paper lantern", version: "1.0" }, { emoji: "🪔", category: 6, name: "diya lamp", version: "12.0" }, { emoji: "📔", category: 6, name: "notebook with decorative cover", version: "1.0" }, { emoji: "📕", category: 6, name: "closed book", version: "1.0" }, { emoji: "📖", category: 6, name: "open book", version: "1.0" }, { emoji: "📗", category: 6, name: "green book", version: "1.0" }, { emoji: "📘", category: 6, name: "blue book", version: "1.0" }, { emoji: "📙", category: 6, name: "orange book", version: "1.0" }, { emoji: "📚", category: 6, name: "books", version: "1.0" }, { emoji: "📓", category: 6, name: "notebook", version: "1.0" }, { emoji: "📒", category: 6, name: "ledger", version: "1.0" }, { emoji: "📃", category: 6, name: "page with curl", version: "1.0" }, { emoji: "📜", category: 6, name: "scroll", version: "1.0" }, { emoji: "📄", category: 6, name: "page facing up", version: "1.0" }, { emoji: "📰", category: 6, name: "newspaper", version: "1.0" }, { emoji: "🗞ï¸", category: 6, name: "rolled-up newspaper", version: "1.0" }, { emoji: "📑", category: 6, name: "bookmark tabs", version: "1.0" }, { emoji: "🔖", category: 6, name: "bookmark", version: "1.0" }, { emoji: "ðŸ·ï¸", category: 6, name: "label", version: "1.0" }, { emoji: "💰", category: 6, name: "money bag", version: "1.0" }, { emoji: "🪙", category: 6, name: "coin", version: "13.0" }, { emoji: "💴", category: 6, name: "yen banknote", version: "1.0" }, { emoji: "💵", category: 6, name: "dollar banknote", version: "1.0" }, { emoji: "💶", category: 6, name: "euro banknote", version: "1.0" }, { emoji: "💷", category: 6, name: "pound banknote", version: "1.0" }, { emoji: "💸", category: 6, name: "money with wings", version: "1.0" }, { emoji: "💳", category: 6, name: "credit card", version: "1.0" }, { emoji: "🧾", category: 6, name: "receipt", version: "11.0" }, { emoji: "💹", category: 6, name: "chart increasing with yen", version: "1.0" }, { emoji: "✉ï¸", category: 6, name: "envelope", version: "1.0" }, { emoji: "📧", category: 6, name: "e-mail", version: "1.0" }, { emoji: "📨", category: 6, name: "incoming envelope", version: "1.0" }, { emoji: "📩", category: 6, name: "envelope with arrow", version: "1.0" }, { emoji: "📤", category: 6, name: "outbox tray", version: "1.0" }, { emoji: "📥", category: 6, name: "inbox tray", version: "1.0" }, { emoji: "📦", category: 6, name: "package", version: "1.0" }, { emoji: "📫", category: 6, name: "closed mailbox with raised flag", version: "1.0" }, { emoji: "📪", category: 6, name: "closed mailbox with lowered flag", version: "1.0" }, { emoji: "📬", category: 6, name: "open mailbox with raised flag", version: "1.0" }, { emoji: "ðŸ“", category: 6, name: "open mailbox with lowered flag", version: "1.0" }, { emoji: "📮", category: 6, name: "postbox", version: "1.0" }, { emoji: "🗳ï¸", category: 6, name: "ballot box with ballot", version: "1.0" }, { emoji: "âœï¸", category: 6, name: "pencil", version: "1.0" }, { emoji: "✒ï¸", category: 6, name: "black nib", version: "1.0" }, { emoji: "🖋ï¸", category: 6, name: "fountain pen", version: "1.0" }, { emoji: "🖊ï¸", category: 6, name: "pen", version: "1.0" }, { emoji: "🖌ï¸", category: 6, name: "paintbrush", version: "1.0" }, { emoji: "ðŸ–ï¸", category: 6, name: "crayon", version: "1.0" }, { emoji: "ðŸ“", category: 6, name: "memo", version: "1.0" }, { emoji: "💼", category: 6, name: "briefcase", version: "1.0" }, { emoji: "ðŸ“", category: 6, name: "file folder", version: "1.0" }, { emoji: "📂", category: 6, name: "open file folder", version: "1.0" }, { emoji: "🗂ï¸", category: 6, name: "card index dividers", version: "1.0" }, { emoji: "📅", category: 6, name: "calendar", version: "1.0" }, { emoji: "📆", category: 6, name: "tear-off calendar", version: "1.0" }, { emoji: "🗒ï¸", category: 6, name: "spiral notepad", version: "1.0" }, { emoji: "🗓ï¸", category: 6, name: "spiral calendar", version: "1.0" }, { emoji: "📇", category: 6, name: "card index", version: "1.0" }, { emoji: "📈", category: 6, name: "chart increasing", version: "1.0" }, { emoji: "📉", category: 6, name: "chart decreasing", version: "1.0" }, { emoji: "📊", category: 6, name: "bar chart", version: "1.0" }, { emoji: "📋", category: 6, name: "clipboard", version: "1.0" }, { emoji: "📌", category: 6, name: "pushpin", version: "1.0" }, { emoji: "ðŸ“", category: 6, name: "round pushpin", version: "1.0" }, { emoji: "📎", category: 6, name: "paperclip", version: "1.0" }, { emoji: "🖇ï¸", category: 6, name: "linked paperclips", version: "1.0" }, { emoji: "ðŸ“", category: 6, name: "straight ruler", version: "1.0" }, { emoji: "ðŸ“", category: 6, name: "triangular ruler", version: "1.0" }, { emoji: "✂ï¸", category: 6, name: "scissors", version: "1.0" }, { emoji: "🗃ï¸", category: 6, name: "card file box", version: "1.0" }, { emoji: "🗄ï¸", category: 6, name: "file cabinet", version: "1.0" }, { emoji: "🗑ï¸", category: 6, name: "wastebasket", version: "1.0" }, { emoji: "🔒", category: 6, name: "locked", version: "1.0" }, { emoji: "🔓", category: 6, name: "unlocked", version: "1.0" }, { emoji: "ðŸ”", category: 6, name: "locked with pen", version: "1.0" }, { emoji: "ðŸ”", category: 6, name: "locked with key", version: "1.0" }, { emoji: "🔑", category: 6, name: "key", version: "1.0" }, { emoji: "ðŸ—ï¸", category: 6, name: "old key", version: "1.0" }, { emoji: "🔨", category: 6, name: "hammer", version: "1.0" }, { emoji: "🪓", category: 6, name: "axe", version: "12.0" }, { emoji: "â›ï¸", category: 6, name: "pick", version: "1.0" }, { emoji: "âš’ï¸", category: 6, name: "hammer and pick", version: "1.0" }, { emoji: "🛠ï¸", category: 6, name: "hammer and wrench", version: "1.0" }, { emoji: "🗡ï¸", category: 6, name: "dagger", version: "1.0" }, { emoji: "âš”ï¸", category: 6, name: "crossed swords", version: "1.0" }, { emoji: "🔫", category: 6, name: "pistol", version: "1.0" }, { emoji: "🪃", category: 6, name: "boomerang", version: "13.0" }, { emoji: "ðŸ¹", category: 6, name: "bow and arrow", version: "1.0" }, { emoji: "🛡ï¸", category: 6, name: "shield", version: "1.0" }, { emoji: "🪚", category: 6, name: "carpentry saw", version: "13.0" }, { emoji: "🔧", category: 6, name: "wrench", version: "1.0" }, { emoji: "🪛", category: 6, name: "screwdriver", version: "13.0" }, { emoji: "🔩", category: 6, name: "nut and bolt", version: "1.0" }, { emoji: "âš™ï¸", category: 6, name: "gear", version: "1.0" }, { emoji: "🗜ï¸", category: 6, name: "clamp", version: "1.0" }, { emoji: "âš–ï¸", category: 6, name: "balance scale", version: "1.0" }, { emoji: "🦯", category: 6, name: "white cane", version: "12.0" }, { emoji: "🔗", category: 6, name: "link", version: "1.0" }, { emoji: "⛓ï¸", category: 6, name: "chains", version: "1.0" }, { emoji: "ðŸª", category: 6, name: "hook", version: "13.0" }, { emoji: "🧰", category: 6, name: "toolbox", version: "11.0" }, { emoji: "🧲", category: 6, name: "magnet", version: "11.0" }, { emoji: "🪜", category: 6, name: "ladder", version: "13.0" }, { emoji: "âš—ï¸", category: 6, name: "alembic", version: "1.0" }, { emoji: "🧪", category: 6, name: "test tube", version: "11.0" }, { emoji: "🧫", category: 6, name: "petri dish", version: "11.0" }, { emoji: "🧬", category: 6, name: "dna", version: "11.0" }, { emoji: "🔬", category: 6, name: "microscope", version: "1.0" }, { emoji: "ðŸ”", category: 6, name: "telescope", version: "1.0" }, { emoji: "📡", category: 6, name: "satellite antenna", version: "1.0" }, { emoji: "💉", category: 6, name: "syringe", version: "1.0" }, { emoji: "🩸", category: 6, name: "drop of blood", version: "12.0" }, { emoji: "💊", category: 6, name: "pill", version: "1.0" }, { emoji: "🩹", category: 6, name: "adhesive bandage", version: "12.0" }, { emoji: "🩺", category: 6, name: "stethoscope", version: "12.0" }, { emoji: "🚪", category: 6, name: "door", version: "1.0" }, { emoji: "🛗", category: 6, name: "elevator", version: "13.0" }, { emoji: "🪞", category: 6, name: "mirror", version: "13.0" }, { emoji: "🪟", category: 6, name: "window", version: "13.0" }, { emoji: "ðŸ›ï¸", category: 6, name: "bed", version: "1.0" }, { emoji: "🛋ï¸", category: 6, name: "couch and lamp", version: "1.0" }, { emoji: "🪑", category: 6, name: "chair", version: "12.0" }, { emoji: "🚽", category: 6, name: "toilet", version: "1.0" }, { emoji: "🪠", category: 6, name: "plunger", version: "13.0" }, { emoji: "🚿", category: 6, name: "shower", version: "1.0" }, { emoji: "ðŸ›", category: 6, name: "bathtub", version: "1.0" }, { emoji: "🪤", category: 6, name: "mouse trap", version: "13.0" }, { emoji: "🪒", category: 6, name: "razor", version: "12.0" }, { emoji: "🧴", category: 6, name: "lotion bottle", version: "11.0" }, { emoji: "🧷", category: 6, name: "safety pin", version: "11.0" }, { emoji: "🧹", category: 6, name: "broom", version: "11.0" }, { emoji: "🧺", category: 6, name: "basket", version: "11.0" }, { emoji: "🧻", category: 6, name: "roll of paper", version: "11.0" }, { emoji: "🪣", category: 6, name: "bucket", version: "13.0" }, { emoji: "🧼", category: 6, name: "soap", version: "11.0" }, { emoji: "🪥", category: 6, name: "toothbrush", version: "13.0" }, { emoji: "🧽", category: 6, name: "sponge", version: "11.0" }, { emoji: "🧯", category: 6, name: "fire extinguisher", version: "11.0" }, { emoji: "🛒", category: 6, name: "shopping cart", version: "3.0" }, { emoji: "🚬", category: 6, name: "cigarette", version: "1.0" }, { emoji: "âš°ï¸", category: 6, name: "coffin", version: "1.0" }, { emoji: "🪦", category: 6, name: "headstone", version: "13.0" }, { emoji: "âš±ï¸", category: 6, name: "funeral urn", version: "1.0" }, { emoji: "🗿", category: 6, name: "moai", version: "1.0" }, { emoji: "🪧", category: 6, name: "placard", version: "13.0" }, { emoji: "ðŸ§", category: 7, name: "ATM sign", version: "1.0" }, { emoji: "🚮", category: 7, name: "litter in bin sign", version: "1.0" }, { emoji: "🚰", category: 7, name: "potable water", version: "1.0" }, { emoji: "♿", category: 7, name: "wheelchair symbol", version: "1.0" }, { emoji: "🚹", category: 7, name: "men’s room", version: "1.0" }, { emoji: "🚺", category: 7, name: "women’s room", version: "1.0" }, { emoji: "🚻", category: 7, name: "restroom", version: "1.0" }, { emoji: "🚼", category: 7, name: "baby symbol", version: "1.0" }, { emoji: "🚾", category: 7, name: "water closet", version: "1.0" }, { emoji: "🛂", category: 7, name: "passport control", version: "1.0" }, { emoji: "🛃", category: 7, name: "customs", version: "1.0" }, { emoji: "🛄", category: 7, name: "baggage claim", version: "1.0" }, { emoji: "🛅", category: 7, name: "left luggage", version: "1.0" }, { emoji: "âš ï¸", category: 7, name: "warning", version: "1.0" }, { emoji: "🚸", category: 7, name: "children crossing", version: "1.0" }, { emoji: "â›”", category: 7, name: "no entry", version: "1.0" }, { emoji: "🚫", category: 7, name: "prohibited", version: "1.0" }, { emoji: "🚳", category: 7, name: "no bicycles", version: "1.0" }, { emoji: "ðŸš", category: 7, name: "no smoking", version: "1.0" }, { emoji: "🚯", category: 7, name: "no littering", version: "1.0" }, { emoji: "🚱", category: 7, name: "non-potable water", version: "1.0" }, { emoji: "🚷", category: 7, name: "no pedestrians", version: "1.0" }, { emoji: "📵", category: 7, name: "no mobile phones", version: "1.0" }, { emoji: "🔞", category: 7, name: "no one under eighteen", version: "1.0" }, { emoji: "☢ï¸", category: 7, name: "radioactive", version: "1.0" }, { emoji: "☣ï¸", category: 7, name: "biohazard", version: "1.0" }, { emoji: "⬆ï¸", category: 7, name: "up arrow", version: "1.0" }, { emoji: "↗ï¸", category: 7, name: "up-right arrow", version: "1.0" }, { emoji: "âž¡ï¸", category: 7, name: "right arrow", version: "1.0" }, { emoji: "↘ï¸", category: 7, name: "down-right arrow", version: "1.0" }, { emoji: "⬇ï¸", category: 7, name: "down arrow", version: "1.0" }, { emoji: "↙ï¸", category: 7, name: "down-left arrow", version: "1.0" }, { emoji: "⬅ï¸", category: 7, name: "left arrow", version: "1.0" }, { emoji: "↖ï¸", category: 7, name: "up-left arrow", version: "1.0" }, { emoji: "↕ï¸", category: 7, name: "up-down arrow", version: "1.0" }, { emoji: "↔ï¸", category: 7, name: "left-right arrow", version: "1.0" }, { emoji: "↩ï¸", category: 7, name: "right arrow curving left", version: "1.0" }, { emoji: "↪ï¸", category: 7, name: "left arrow curving right", version: "1.0" }, { emoji: "⤴ï¸", category: 7, name: "right arrow curving up", version: "1.0" }, { emoji: "⤵ï¸", category: 7, name: "right arrow curving down", version: "1.0" }, { emoji: "🔃", category: 7, name: "clockwise vertical arrows", version: "1.0" }, { emoji: "🔄", category: 7, name: "counterclockwise arrows button", version: "1.0" }, { emoji: "🔙", category: 7, name: "BACK arrow", version: "1.0" }, { emoji: "🔚", category: 7, name: "END arrow", version: "1.0" }, { emoji: "🔛", category: 7, name: "ON! arrow", version: "1.0" }, { emoji: "🔜", category: 7, name: "SOON arrow", version: "1.0" }, { emoji: "ðŸ”", category: 7, name: "TOP arrow", version: "1.0" }, { emoji: "ðŸ›", category: 7, name: "place of worship", version: "1.0" }, { emoji: "âš›ï¸", category: 7, name: "atom symbol", version: "1.0" }, { emoji: "🕉ï¸", category: 7, name: "om", version: "1.0" }, { emoji: "✡ï¸", category: 7, name: "star of David", version: "1.0" }, { emoji: "☸ï¸", category: 7, name: "wheel of dharma", version: "1.0" }, { emoji: "☯ï¸", category: 7, name: "yin yang", version: "1.0" }, { emoji: "âœï¸", category: 7, name: "latin cross", version: "1.0" }, { emoji: "☦ï¸", category: 7, name: "orthodox cross", version: "1.0" }, { emoji: "☪ï¸", category: 7, name: "star and crescent", version: "1.0" }, { emoji: "☮ï¸", category: 7, name: "peace symbol", version: "1.0" }, { emoji: "🕎", category: 7, name: "menorah", version: "1.0" }, { emoji: "🔯", category: 7, name: "dotted six-pointed star", version: "1.0" }, { emoji: "♈", category: 7, name: "Aries", version: "1.0" }, { emoji: "♉", category: 7, name: "Taurus", version: "1.0" }, { emoji: "♊", category: 7, name: "Gemini", version: "1.0" }, { emoji: "♋", category: 7, name: "Cancer", version: "1.0" }, { emoji: "♌", category: 7, name: "Leo", version: "1.0" }, { emoji: "â™", category: 7, name: "Virgo", version: "1.0" }, { emoji: "♎", category: 7, name: "Libra", version: "1.0" }, { emoji: "â™", category: 7, name: "Scorpio", version: "1.0" }, { emoji: "â™", category: 7, name: "Sagittarius", version: "1.0" }, { emoji: "♑", category: 7, name: "Capricorn", version: "1.0" }, { emoji: "â™’", category: 7, name: "Aquarius", version: "1.0" }, { emoji: "♓", category: 7, name: "Pisces", version: "1.0" }, { emoji: "⛎", category: 7, name: "Ophiuchus", version: "1.0" }, { emoji: "🔀", category: 7, name: "shuffle tracks button", version: "1.0" }, { emoji: "ðŸ”", category: 7, name: "repeat button", version: "1.0" }, { emoji: "🔂", category: 7, name: "repeat single button", version: "1.0" }, { emoji: "â–¶ï¸", category: 7, name: "play button", version: "1.0" }, { emoji: "â©", category: 7, name: "fast-forward button", version: "1.0" }, { emoji: "âï¸", category: 7, name: "next track button", version: "1.0" }, { emoji: "â¯ï¸", category: 7, name: "play or pause button", version: "1.0" }, { emoji: "â—€ï¸", category: 7, name: "reverse button", version: "1.0" }, { emoji: "âª", category: 7, name: "fast reverse button", version: "1.0" }, { emoji: "â®ï¸", category: 7, name: "last track button", version: "1.0" }, { emoji: "🔼", category: 7, name: "upwards button", version: "1.0" }, { emoji: "â«", category: 7, name: "fast up button", version: "1.0" }, { emoji: "🔽", category: 7, name: "downwards button", version: "1.0" }, { emoji: "â¬", category: 7, name: "fast down button", version: "1.0" }, { emoji: "â¸ï¸", category: 7, name: "pause button", version: "1.0" }, { emoji: "â¹ï¸", category: 7, name: "stop button", version: "1.0" }, { emoji: "âºï¸", category: 7, name: "record button", version: "1.0" }, { emoji: "âï¸", category: 7, name: "eject button", version: "1.0" }, { emoji: "🎦", category: 7, name: "cinema", version: "1.0" }, { emoji: "🔅", category: 7, name: "dim button", version: "1.0" }, { emoji: "🔆", category: 7, name: "bright button", version: "1.0" }, { emoji: "📶", category: 7, name: "antenna bars", version: "1.0" }, { emoji: "📳", category: 7, name: "vibration mode", version: "1.0" }, { emoji: "📴", category: 7, name: "mobile phone off", version: "1.0" }, { emoji: "♀ï¸", category: 7, name: "female sign", version: "4.0" }, { emoji: "♂ï¸", category: 7, name: "male sign", version: "4.0" }, { emoji: "⚧ï¸", category: 7, name: "transgender symbol", version: "13.0" }, { emoji: "✖ï¸", category: 7, name: "multiply", version: "1.0" }, { emoji: "âž•", category: 7, name: "plus", version: "1.0" }, { emoji: "âž–", category: 7, name: "minus", version: "1.0" }, { emoji: "âž—", category: 7, name: "divide", version: "1.0" }, { emoji: "♾ï¸", category: 7, name: "infinity", version: "11.0" }, { emoji: "‼ï¸", category: 7, name: "double exclamation mark", version: "1.0" }, { emoji: "â‰ï¸", category: 7, name: "exclamation question mark", version: "1.0" }, { emoji: "â“", category: 7, name: "question mark", version: "1.0" }, { emoji: "â”", category: 7, name: "white question mark", version: "1.0" }, { emoji: "â•", category: 7, name: "white exclamation mark", version: "1.0" }, { emoji: "â—", category: 7, name: "exclamation mark", version: "1.0" }, { emoji: "〰ï¸", category: 7, name: "wavy dash", version: "1.0" }, { emoji: "💱", category: 7, name: "currency exchange", version: "1.0" }, { emoji: "💲", category: 7, name: "heavy dollar sign", version: "1.0" }, { emoji: "âš•ï¸", category: 7, name: "medical symbol", version: "4.0" }, { emoji: "â™»ï¸", category: 7, name: "recycling symbol", version: "1.0" }, { emoji: "âšœï¸", category: 7, name: "fleur-de-lis", version: "1.0" }, { emoji: "🔱", category: 7, name: "trident emblem", version: "1.0" }, { emoji: "📛", category: 7, name: "name badge", version: "1.0" }, { emoji: "🔰", category: 7, name: "Japanese symbol for beginner", version: "1.0" }, { emoji: "â•", category: 7, name: "hollow red circle", version: "1.0" }, { emoji: "✅", category: 7, name: "check mark button", version: "1.0" }, { emoji: "☑ï¸", category: 7, name: "check box with check", version: "1.0" }, { emoji: "✔ï¸", category: 7, name: "check mark", version: "1.0" }, { emoji: "âŒ", category: 7, name: "cross mark", version: "1.0" }, { emoji: "âŽ", category: 7, name: "cross mark button", version: "1.0" }, { emoji: "âž°", category: 7, name: "curly loop", version: "1.0" }, { emoji: "âž¿", category: 7, name: "double curly loop", version: "1.0" }, { emoji: "〽ï¸", category: 7, name: "part alternation mark", version: "1.0" }, { emoji: "✳ï¸", category: 7, name: "eight-spoked asterisk", version: "1.0" }, { emoji: "✴ï¸", category: 7, name: "eight-pointed star", version: "1.0" }, { emoji: "â‡ï¸", category: 7, name: "sparkle", version: "1.0" }, { emoji: "©ï¸", category: 7, name: "copyright", version: "1.0" }, { emoji: "®ï¸", category: 7, name: "registered", version: "1.0" }, { emoji: "â„¢ï¸", category: 7, name: "trade mark", version: "1.0" }, { emoji: "#ï¸âƒ£", category: 7, name: "keycap: #", version: "1.0" }, { emoji: "*ï¸âƒ£", category: 7, name: "keycap: *", version: "2.0" }, { emoji: "0ï¸âƒ£", category: 7, name: "keycap: 0", version: "1.0" }, { emoji: "1ï¸âƒ£", category: 7, name: "keycap: 1", version: "1.0" }, { emoji: "2ï¸âƒ£", category: 7, name: "keycap: 2", version: "1.0" }, { emoji: "3ï¸âƒ£", category: 7, name: "keycap: 3", version: "1.0" }, { emoji: "4ï¸âƒ£", category: 7, name: "keycap: 4", version: "1.0" }, { emoji: "5ï¸âƒ£", category: 7, name: "keycap: 5", version: "1.0" }, { emoji: "6ï¸âƒ£", category: 7, name: "keycap: 6", version: "1.0" }, { emoji: "7ï¸âƒ£", category: 7, name: "keycap: 7", version: "1.0" }, { emoji: "8ï¸âƒ£", category: 7, name: "keycap: 8", version: "1.0" }, { emoji: "9ï¸âƒ£", category: 7, name: "keycap: 9", version: "1.0" }, { emoji: "🔟", category: 7, name: "keycap: 10", version: "1.0" }, { emoji: "🔠", category: 7, name: "input latin uppercase", version: "1.0" }, { emoji: "🔡", category: 7, name: "input latin lowercase", version: "1.0" }, { emoji: "🔢", category: 7, name: "input numbers", version: "1.0" }, { emoji: "🔣", category: 7, name: "input symbols", version: "1.0" }, { emoji: "🔤", category: 7, name: "input latin letters", version: "1.0" }, { emoji: "🅰ï¸", category: 7, name: "A button (blood type)", version: "1.0" }, { emoji: "🆎", category: 7, name: "AB button (blood type)", version: "1.0" }, { emoji: "🅱ï¸", category: 7, name: "B button (blood type)", version: "1.0" }, { emoji: "🆑", category: 7, name: "CL button", version: "1.0" }, { emoji: "🆒", category: 7, name: "COOL button", version: "1.0" }, { emoji: "🆓", category: 7, name: "FREE button", version: "1.0" }, { emoji: "ℹï¸", category: 7, name: "information", version: "1.0" }, { emoji: "🆔", category: 7, name: "ID button", version: "1.0" }, { emoji: "â“‚ï¸", category: 7, name: "circled M", version: "1.0" }, { emoji: "🆕", category: 7, name: "NEW button", version: "1.0" }, { emoji: "🆖", category: 7, name: "NG button", version: "1.0" }, { emoji: "🅾ï¸", category: 7, name: "O button (blood type)", version: "1.0" }, { emoji: "🆗", category: 7, name: "OK button", version: "1.0" }, { emoji: "🅿ï¸", category: 7, name: "P button", version: "1.0" }, { emoji: "🆘", category: 7, name: "SOS button", version: "1.0" }, { emoji: "🆙", category: 7, name: "UP! button", version: "1.0" }, { emoji: "🆚", category: 7, name: "VS button", version: "1.0" }, { emoji: "ðŸˆ", category: 7, name: "Japanese “here†button", version: "1.0" }, { emoji: "🈂ï¸", category: 7, name: "Japanese “service charge†button", version: "1.0" }, { emoji: "🈷ï¸", category: 7, name: "Japanese “monthly amount†button", version: "1.0" }, { emoji: "🈶", category: 7, name: "Japanese “not free of charge†button", version: "1.0" }, { emoji: "🈯", category: 7, name: "Japanese “reserved†button", version: "1.0" }, { emoji: "ðŸ‰", category: 7, name: "Japanese “bargain†button", version: "1.0" }, { emoji: "🈹", category: 7, name: "Japanese “discount†button", version: "1.0" }, { emoji: "🈚", category: 7, name: "Japanese “free of charge†button", version: "1.0" }, { emoji: "🈲", category: 7, name: "Japanese “prohibited†button", version: "1.0" }, { emoji: "🉑", category: 7, name: "Japanese “acceptable†button", version: "1.0" }, { emoji: "🈸", category: 7, name: "Japanese “application†button", version: "1.0" }, { emoji: "🈴", category: 7, name: "Japanese “passing grade†button", version: "1.0" }, { emoji: "🈳", category: 7, name: "Japanese “vacancy†button", version: "1.0" }, { emoji: "㊗ï¸", category: 7, name: "Japanese “congratulations†button", version: "1.0" }, { emoji: "㊙ï¸", category: 7, name: "Japanese “secret†button", version: "1.0" }, { emoji: "🈺", category: 7, name: "Japanese “open for business†button", version: "1.0" }, { emoji: "🈵", category: 7, name: "Japanese “no vacancy†button", version: "1.0" }, { emoji: "🔴", category: 7, name: "red circle", version: "1.0" }, { emoji: "🟠", category: 7, name: "orange circle", version: "12.0" }, { emoji: "🟡", category: 7, name: "yellow circle", version: "12.0" }, { emoji: "🟢", category: 7, name: "green circle", version: "12.0" }, { emoji: "🔵", category: 7, name: "blue circle", version: "1.0" }, { emoji: "🟣", category: 7, name: "purple circle", version: "12.0" }, { emoji: "🟤", category: 7, name: "brown circle", version: "12.0" }, { emoji: "âš«", category: 7, name: "black circle", version: "1.0" }, { emoji: "⚪", category: 7, name: "white circle", version: "1.0" }, { emoji: "🟥", category: 7, name: "red square", version: "12.0" }, { emoji: "🟧", category: 7, name: "orange square", version: "12.0" }, { emoji: "🟨", category: 7, name: "yellow square", version: "12.0" }, { emoji: "🟩", category: 7, name: "green square", version: "12.0" }, { emoji: "🟦", category: 7, name: "blue square", version: "12.0" }, { emoji: "🟪", category: 7, name: "purple square", version: "12.0" }, { emoji: "🟫", category: 7, name: "brown square", version: "12.0" }, { emoji: "⬛", category: 7, name: "black large square", version: "1.0" }, { emoji: "⬜", category: 7, name: "white large square", version: "1.0" }, { emoji: "â—¼ï¸", category: 7, name: "black medium square", version: "1.0" }, { emoji: "â—»ï¸", category: 7, name: "white medium square", version: "1.0" }, { emoji: "â—¾", category: 7, name: "black medium-small square", version: "1.0" }, { emoji: "â—½", category: 7, name: "white medium-small square", version: "1.0" }, { emoji: "â–ªï¸", category: 7, name: "black small square", version: "1.0" }, { emoji: "â–«ï¸", category: 7, name: "white small square", version: "1.0" }, { emoji: "🔶", category: 7, name: "large orange diamond", version: "1.0" }, { emoji: "🔷", category: 7, name: "large blue diamond", version: "1.0" }, { emoji: "🔸", category: 7, name: "small orange diamond", version: "1.0" }, { emoji: "🔹", category: 7, name: "small blue diamond", version: "1.0" }, { emoji: "🔺", category: 7, name: "red triangle pointed up", version: "1.0" }, { emoji: "🔻", category: 7, name: "red triangle pointed down", version: "1.0" }, { emoji: "💠", category: 7, name: "diamond with a dot", version: "1.0" }, { emoji: "🔘", category: 7, name: "radio button", version: "1.0" }, { emoji: "🔳", category: 7, name: "white square button", version: "1.0" }, { emoji: "🔲", category: 7, name: "black square button", version: "1.0" }, { emoji: "ðŸ", category: 8, name: "chequered flag", version: "1.0" }, { emoji: "🚩", category: 8, name: "triangular flag", version: "1.0" }, { emoji: "🎌", category: 8, name: "crossed flags", version: "1.0" }, { emoji: "ðŸ´", category: 8, name: "black flag", version: "1.0" }, { emoji: "ðŸ³ï¸", category: 8, name: "white flag", version: "1.0" }, { emoji: "ðŸ³ï¸â€ðŸŒˆ", category: 8, name: "rainbow flag", version: "4.0" }, { emoji: "ðŸ³ï¸â€âš§ï¸", category: 8, name: "transgender flag", version: "13.0" }, { emoji: "ðŸ´â€â˜ ï¸", category: 8, name: "pirate flag", version: "11.0" }, { emoji: "🇦🇨", category: 8, name: "flag: Ascension Island", version: "2.0" }, { emoji: "🇦🇩", category: 8, name: "flag: Andorra", version: "2.0" }, { emoji: "🇦🇪", category: 8, name: "flag: United Arab Emirates", version: "2.0" }, { emoji: "🇦🇫", category: 8, name: "flag: Afghanistan", version: "2.0" }, { emoji: "🇦🇬", category: 8, name: "flag: Antigua & Barbuda", version: "2.0" }, { emoji: "🇦🇮", category: 8, name: "flag: Anguilla", version: "2.0" }, { emoji: "🇦🇱", category: 8, name: "flag: Albania", version: "2.0" }, { emoji: "🇦🇲", category: 8, name: "flag: Armenia", version: "2.0" }, { emoji: "🇦🇴", category: 8, name: "flag: Angola", version: "2.0" }, { emoji: "🇦🇶", category: 8, name: "flag: Antarctica", version: "2.0" }, { emoji: "🇦🇷", category: 8, name: "flag: Argentina", version: "2.0" }, { emoji: "🇦🇸", category: 8, name: "flag: American Samoa", version: "2.0" }, { emoji: "🇦🇹", category: 8, name: "flag: Austria", version: "2.0" }, { emoji: "🇦🇺", category: 8, name: "flag: Australia", version: "2.0" }, { emoji: "🇦🇼", category: 8, name: "flag: Aruba", version: "2.0" }, { emoji: "🇦🇽", category: 8, name: "flag: Ã…land Islands", version: "2.0" }, { emoji: "🇦🇿", category: 8, name: "flag: Azerbaijan", version: "2.0" }, { emoji: "🇧🇦", category: 8, name: "flag: Bosnia & Herzegovina", version: "2.0" }, { emoji: "🇧🇧", category: 8, name: "flag: Barbados", version: "2.0" }, { emoji: "🇧🇩", category: 8, name: "flag: Bangladesh", version: "2.0" }, { emoji: "🇧🇪", category: 8, name: "flag: Belgium", version: "2.0" }, { emoji: "🇧🇫", category: 8, name: "flag: Burkina Faso", version: "2.0" }, { emoji: "🇧🇬", category: 8, name: "flag: Bulgaria", version: "2.0" }, { emoji: "🇧ðŸ‡", category: 8, name: "flag: Bahrain", version: "2.0" }, { emoji: "🇧🇮", category: 8, name: "flag: Burundi", version: "2.0" }, { emoji: "🇧🇯", category: 8, name: "flag: Benin", version: "2.0" }, { emoji: "🇧🇱", category: 8, name: "flag: St. Barthélemy", version: "2.0" }, { emoji: "🇧🇲", category: 8, name: "flag: Bermuda", version: "2.0" }, { emoji: "🇧🇳", category: 8, name: "flag: Brunei", version: "2.0" }, { emoji: "🇧🇴", category: 8, name: "flag: Bolivia", version: "2.0" }, { emoji: "🇧🇶", category: 8, name: "flag: Caribbean Netherlands", version: "2.0" }, { emoji: "🇧🇷", category: 8, name: "flag: Brazil", version: "2.0" }, { emoji: "🇧🇸", category: 8, name: "flag: Bahamas", version: "2.0" }, { emoji: "🇧🇹", category: 8, name: "flag: Bhutan", version: "2.0" }, { emoji: "🇧🇻", category: 8, name: "flag: Bouvet Island", version: "2.0" }, { emoji: "🇧🇼", category: 8, name: "flag: Botswana", version: "2.0" }, { emoji: "🇧🇾", category: 8, name: "flag: Belarus", version: "2.0" }, { emoji: "🇧🇿", category: 8, name: "flag: Belize", version: "2.0" }, { emoji: "🇨🇦", category: 8, name: "flag: Canada", version: "2.0" }, { emoji: "🇨🇨", category: 8, name: "flag: Cocos (Keeling) Islands", version: "2.0" }, { emoji: "🇨🇩", category: 8, name: "flag: Congo - Kinshasa", version: "2.0" }, { emoji: "🇨🇫", category: 8, name: "flag: Central African Republic", version: "2.0" }, { emoji: "🇨🇬", category: 8, name: "flag: Congo - Brazzaville", version: "2.0" }, { emoji: "🇨ðŸ‡", category: 8, name: "flag: Switzerland", version: "2.0" }, { emoji: "🇨🇮", category: 8, name: "flag: Côte d’Ivoire", version: "2.0" }, { emoji: "🇨🇰", category: 8, name: "flag: Cook Islands", version: "2.0" }, { emoji: "🇨🇱", category: 8, name: "flag: Chile", version: "2.0" }, { emoji: "🇨🇲", category: 8, name: "flag: Cameroon", version: "2.0" }, { emoji: "🇨🇳", category: 8, name: "flag: China", version: "1.0" }, { emoji: "🇨🇴", category: 8, name: "flag: Colombia", version: "2.0" }, { emoji: "🇨🇵", category: 8, name: "flag: Clipperton Island", version: "2.0" }, { emoji: "🇨🇷", category: 8, name: "flag: Costa Rica", version: "2.0" }, { emoji: "🇨🇺", category: 8, name: "flag: Cuba", version: "2.0" }, { emoji: "🇨🇻", category: 8, name: "flag: Cape Verde", version: "2.0" }, { emoji: "🇨🇼", category: 8, name: "flag: Curaçao", version: "2.0" }, { emoji: "🇨🇽", category: 8, name: "flag: Christmas Island", version: "2.0" }, { emoji: "🇨🇾", category: 8, name: "flag: Cyprus", version: "2.0" }, { emoji: "🇨🇿", category: 8, name: "flag: Czechia", version: "2.0" }, { emoji: "🇩🇪", category: 8, name: "flag: Germany", version: "1.0" }, { emoji: "🇩🇬", category: 8, name: "flag: Diego Garcia", version: "2.0" }, { emoji: "🇩🇯", category: 8, name: "flag: Djibouti", version: "2.0" }, { emoji: "🇩🇰", category: 8, name: "flag: Denmark", version: "2.0" }, { emoji: "🇩🇲", category: 8, name: "flag: Dominica", version: "2.0" }, { emoji: "🇩🇴", category: 8, name: "flag: Dominican Republic", version: "2.0" }, { emoji: "🇩🇿", category: 8, name: "flag: Algeria", version: "2.0" }, { emoji: "🇪🇦", category: 8, name: "flag: Ceuta & Melilla", version: "2.0" }, { emoji: "🇪🇨", category: 8, name: "flag: Ecuador", version: "2.0" }, { emoji: "🇪🇪", category: 8, name: "flag: Estonia", version: "2.0" }, { emoji: "🇪🇬", category: 8, name: "flag: Egypt", version: "2.0" }, { emoji: "🇪ðŸ‡", category: 8, name: "flag: Western Sahara", version: "2.0" }, { emoji: "🇪🇷", category: 8, name: "flag: Eritrea", version: "2.0" }, { emoji: "🇪🇸", category: 8, name: "flag: Spain", version: "1.0" }, { emoji: "🇪🇹", category: 8, name: "flag: Ethiopia", version: "2.0" }, { emoji: "🇪🇺", category: 8, name: "flag: European Union", version: "2.0" }, { emoji: "🇫🇮", category: 8, name: "flag: Finland", version: "2.0" }, { emoji: "🇫🇯", category: 8, name: "flag: Fiji", version: "2.0" }, { emoji: "🇫🇰", category: 8, name: "flag: Falkland Islands", version: "2.0" }, { emoji: "🇫🇲", category: 8, name: "flag: Micronesia", version: "2.0" }, { emoji: "🇫🇴", category: 8, name: "flag: Faroe Islands", version: "2.0" }, { emoji: "🇫🇷", category: 8, name: "flag: France", version: "1.0" }, { emoji: "🇬🇦", category: 8, name: "flag: Gabon", version: "2.0" }, { emoji: "🇬🇧", category: 8, name: "flag: United Kingdom", version: "1.0" }, { emoji: "🇬🇩", category: 8, name: "flag: Grenada", version: "2.0" }, { emoji: "🇬🇪", category: 8, name: "flag: Georgia", version: "2.0" }, { emoji: "🇬🇫", category: 8, name: "flag: French Guiana", version: "2.0" }, { emoji: "🇬🇬", category: 8, name: "flag: Guernsey", version: "2.0" }, { emoji: "🇬ðŸ‡", category: 8, name: "flag: Ghana", version: "2.0" }, { emoji: "🇬🇮", category: 8, name: "flag: Gibraltar", version: "2.0" }, { emoji: "🇬🇱", category: 8, name: "flag: Greenland", version: "2.0" }, { emoji: "🇬🇲", category: 8, name: "flag: Gambia", version: "2.0" }, { emoji: "🇬🇳", category: 8, name: "flag: Guinea", version: "2.0" }, { emoji: "🇬🇵", category: 8, name: "flag: Guadeloupe", version: "2.0" }, { emoji: "🇬🇶", category: 8, name: "flag: Equatorial Guinea", version: "2.0" }, { emoji: "🇬🇷", category: 8, name: "flag: Greece", version: "2.0" }, { emoji: "🇬🇸", category: 8, name: "flag: South Georgia & South Sandwich Islands", version: "2.0" }, { emoji: "🇬🇹", category: 8, name: "flag: Guatemala", version: "2.0" }, { emoji: "🇬🇺", category: 8, name: "flag: Guam", version: "2.0" }, { emoji: "🇬🇼", category: 8, name: "flag: Guinea-Bissau", version: "2.0" }, { emoji: "🇬🇾", category: 8, name: "flag: Guyana", version: "2.0" }, { emoji: "ðŸ‡ðŸ‡°", category: 8, name: "flag: Hong Kong SAR China", version: "2.0" }, { emoji: "ðŸ‡ðŸ‡²", category: 8, name: "flag: Heard & McDonald Islands", version: "2.0" }, { emoji: "ðŸ‡ðŸ‡³", category: 8, name: "flag: Honduras", version: "2.0" }, { emoji: "ðŸ‡ðŸ‡·", category: 8, name: "flag: Croatia", version: "2.0" }, { emoji: "ðŸ‡ðŸ‡¹", category: 8, name: "flag: Haiti", version: "2.0" }, { emoji: "ðŸ‡ðŸ‡º", category: 8, name: "flag: Hungary", version: "2.0" }, { emoji: "🇮🇨", category: 8, name: "flag: Canary Islands", version: "2.0" }, { emoji: "🇮🇩", category: 8, name: "flag: Indonesia", version: "2.0" }, { emoji: "🇮🇪", category: 8, name: "flag: Ireland", version: "2.0" }, { emoji: "🇮🇱", category: 8, name: "flag: Israel", version: "2.0" }, { emoji: "🇮🇲", category: 8, name: "flag: Isle of Man", version: "2.0" }, { emoji: "🇮🇳", category: 8, name: "flag: India", version: "2.0" }, { emoji: "🇮🇴", category: 8, name: "flag: British Indian Ocean Territory", version: "2.0" }, { emoji: "🇮🇶", category: 8, name: "flag: Iraq", version: "2.0" }, { emoji: "🇮🇷", category: 8, name: "flag: Iran", version: "2.0" }, { emoji: "🇮🇸", category: 8, name: "flag: Iceland", version: "2.0" }, { emoji: "🇮🇹", category: 8, name: "flag: Italy", version: "1.0" }, { emoji: "🇯🇪", category: 8, name: "flag: Jersey", version: "2.0" }, { emoji: "🇯🇲", category: 8, name: "flag: Jamaica", version: "2.0" }, { emoji: "🇯🇴", category: 8, name: "flag: Jordan", version: "2.0" }, { emoji: "🇯🇵", category: 8, name: "flag: Japan", version: "1.0" }, { emoji: "🇰🇪", category: 8, name: "flag: Kenya", version: "2.0" }, { emoji: "🇰🇬", category: 8, name: "flag: Kyrgyzstan", version: "2.0" }, { emoji: "🇰ðŸ‡", category: 8, name: "flag: Cambodia", version: "2.0" }, { emoji: "🇰🇮", category: 8, name: "flag: Kiribati", version: "2.0" }, { emoji: "🇰🇲", category: 8, name: "flag: Comoros", version: "2.0" }, { emoji: "🇰🇳", category: 8, name: "flag: St. Kitts & Nevis", version: "2.0" }, { emoji: "🇰🇵", category: 8, name: "flag: North Korea", version: "2.0" }, { emoji: "🇰🇷", category: 8, name: "flag: South Korea", version: "1.0" }, { emoji: "🇰🇼", category: 8, name: "flag: Kuwait", version: "2.0" }, { emoji: "🇰🇾", category: 8, name: "flag: Cayman Islands", version: "2.0" }, { emoji: "🇰🇿", category: 8, name: "flag: Kazakhstan", version: "2.0" }, { emoji: "🇱🇦", category: 8, name: "flag: Laos", version: "2.0" }, { emoji: "🇱🇧", category: 8, name: "flag: Lebanon", version: "2.0" }, { emoji: "🇱🇨", category: 8, name: "flag: St. Lucia", version: "2.0" }, { emoji: "🇱🇮", category: 8, name: "flag: Liechtenstein", version: "2.0" }, { emoji: "🇱🇰", category: 8, name: "flag: Sri Lanka", version: "2.0" }, { emoji: "🇱🇷", category: 8, name: "flag: Liberia", version: "2.0" }, { emoji: "🇱🇸", category: 8, name: "flag: Lesotho", version: "2.0" }, { emoji: "🇱🇹", category: 8, name: "flag: Lithuania", version: "2.0" }, { emoji: "🇱🇺", category: 8, name: "flag: Luxembourg", version: "2.0" }, { emoji: "🇱🇻", category: 8, name: "flag: Latvia", version: "2.0" }, { emoji: "🇱🇾", category: 8, name: "flag: Libya", version: "2.0" }, { emoji: "🇲🇦", category: 8, name: "flag: Morocco", version: "2.0" }, { emoji: "🇲🇨", category: 8, name: "flag: Monaco", version: "2.0" }, { emoji: "🇲🇩", category: 8, name: "flag: Moldova", version: "2.0" }, { emoji: "🇲🇪", category: 8, name: "flag: Montenegro", version: "2.0" }, { emoji: "🇲🇫", category: 8, name: "flag: St. Martin", version: "2.0" }, { emoji: "🇲🇬", category: 8, name: "flag: Madagascar", version: "2.0" }, { emoji: "🇲ðŸ‡", category: 8, name: "flag: Marshall Islands", version: "2.0" }, { emoji: "🇲🇰", category: 8, name: "flag: North Macedonia", version: "2.0" }, { emoji: "🇲🇱", category: 8, name: "flag: Mali", version: "2.0" }, { emoji: "🇲🇲", category: 8, name: "flag: Myanmar (Burma)", version: "2.0" }, { emoji: "🇲🇳", category: 8, name: "flag: Mongolia", version: "2.0" }, { emoji: "🇲🇴", category: 8, name: "flag: Macao SAR China", version: "2.0" }, { emoji: "🇲🇵", category: 8, name: "flag: Northern Mariana Islands", version: "2.0" }, { emoji: "🇲🇶", category: 8, name: "flag: Martinique", version: "2.0" }, { emoji: "🇲🇷", category: 8, name: "flag: Mauritania", version: "2.0" }, { emoji: "🇲🇸", category: 8, name: "flag: Montserrat", version: "2.0" }, { emoji: "🇲🇹", category: 8, name: "flag: Malta", version: "2.0" }, { emoji: "🇲🇺", category: 8, name: "flag: Mauritius", version: "2.0" }, { emoji: "🇲🇻", category: 8, name: "flag: Maldives", version: "2.0" }, { emoji: "🇲🇼", category: 8, name: "flag: Malawi", version: "2.0" }, { emoji: "🇲🇽", category: 8, name: "flag: Mexico", version: "2.0" }, { emoji: "🇲🇾", category: 8, name: "flag: Malaysia", version: "2.0" }, { emoji: "🇲🇿", category: 8, name: "flag: Mozambique", version: "2.0" }, { emoji: "🇳🇦", category: 8, name: "flag: Namibia", version: "2.0" }, { emoji: "🇳🇨", category: 8, name: "flag: New Caledonia", version: "2.0" }, { emoji: "🇳🇪", category: 8, name: "flag: Niger", version: "2.0" }, { emoji: "🇳🇫", category: 8, name: "flag: Norfolk Island", version: "2.0" }, { emoji: "🇳🇬", category: 8, name: "flag: Nigeria", version: "2.0" }, { emoji: "🇳🇮", category: 8, name: "flag: Nicaragua", version: "2.0" }, { emoji: "🇳🇱", category: 8, name: "flag: Netherlands", version: "2.0" }, { emoji: "🇳🇴", category: 8, name: "flag: Norway", version: "2.0" }, { emoji: "🇳🇵", category: 8, name: "flag: Nepal", version: "2.0" }, { emoji: "🇳🇷", category: 8, name: "flag: Nauru", version: "2.0" }, { emoji: "🇳🇺", category: 8, name: "flag: Niue", version: "2.0" }, { emoji: "🇳🇿", category: 8, name: "flag: New Zealand", version: "2.0" }, { emoji: "🇴🇲", category: 8, name: "flag: Oman", version: "2.0" }, { emoji: "🇵🇦", category: 8, name: "flag: Panama", version: "2.0" }, { emoji: "🇵🇪", category: 8, name: "flag: Peru", version: "2.0" }, { emoji: "🇵🇫", category: 8, name: "flag: French Polynesia", version: "2.0" }, { emoji: "🇵🇬", category: 8, name: "flag: Papua New Guinea", version: "2.0" }, { emoji: "🇵ðŸ‡", category: 8, name: "flag: Philippines", version: "2.0" }, { emoji: "🇵🇰", category: 8, name: "flag: Pakistan", version: "2.0" }, { emoji: "🇵🇱", category: 8, name: "flag: Poland", version: "2.0" }, { emoji: "🇵🇲", category: 8, name: "flag: St. Pierre & Miquelon", version: "2.0" }, { emoji: "🇵🇳", category: 8, name: "flag: Pitcairn Islands", version: "2.0" }, { emoji: "🇵🇷", category: 8, name: "flag: Puerto Rico", version: "2.0" }, { emoji: "🇵🇸", category: 8, name: "flag: Palestinian Territories", version: "2.0" }, { emoji: "🇵🇹", category: 8, name: "flag: Portugal", version: "2.0" }, { emoji: "🇵🇼", category: 8, name: "flag: Palau", version: "2.0" }, { emoji: "🇵🇾", category: 8, name: "flag: Paraguay", version: "2.0" }, { emoji: "🇶🇦", category: 8, name: "flag: Qatar", version: "2.0" }, { emoji: "🇷🇪", category: 8, name: "flag: Réunion", version: "2.0" }, { emoji: "🇷🇴", category: 8, name: "flag: Romania", version: "2.0" }, { emoji: "🇷🇸", category: 8, name: "flag: Serbia", version: "2.0" }, { emoji: "🇷🇺", category: 8, name: "flag: Russia", version: "1.0" }, { emoji: "🇷🇼", category: 8, name: "flag: Rwanda", version: "2.0" }, { emoji: "🇸🇦", category: 8, name: "flag: Saudi Arabia", version: "2.0" }, { emoji: "🇸🇧", category: 8, name: "flag: Solomon Islands", version: "2.0" }, { emoji: "🇸🇨", category: 8, name: "flag: Seychelles", version: "2.0" }, { emoji: "🇸🇩", category: 8, name: "flag: Sudan", version: "2.0" }, { emoji: "🇸🇪", category: 8, name: "flag: Sweden", version: "2.0" }, { emoji: "🇸🇬", category: 8, name: "flag: Singapore", version: "2.0" }, { emoji: "🇸ðŸ‡", category: 8, name: "flag: St. Helena", version: "2.0" }, { emoji: "🇸🇮", category: 8, name: "flag: Slovenia", version: "2.0" }, { emoji: "🇸🇯", category: 8, name: "flag: Svalbard & Jan Mayen", version: "2.0" }, { emoji: "🇸🇰", category: 8, name: "flag: Slovakia", version: "2.0" }, { emoji: "🇸🇱", category: 8, name: "flag: Sierra Leone", version: "2.0" }, { emoji: "🇸🇲", category: 8, name: "flag: San Marino", version: "2.0" }, { emoji: "🇸🇳", category: 8, name: "flag: Senegal", version: "2.0" }, { emoji: "🇸🇴", category: 8, name: "flag: Somalia", version: "2.0" }, { emoji: "🇸🇷", category: 8, name: "flag: Suriname", version: "2.0" }, { emoji: "🇸🇸", category: 8, name: "flag: South Sudan", version: "2.0" }, { emoji: "🇸🇹", category: 8, name: "flag: São Tomé & PrÃncipe", version: "2.0" }, { emoji: "🇸🇻", category: 8, name: "flag: El Salvador", version: "2.0" }, { emoji: "🇸🇽", category: 8, name: "flag: Sint Maarten", version: "2.0" }, { emoji: "🇸🇾", category: 8, name: "flag: Syria", version: "2.0" }, { emoji: "🇸🇿", category: 8, name: "flag: Eswatini", version: "2.0" }, { emoji: "🇹🇦", category: 8, name: "flag: Tristan da Cunha", version: "2.0" }, { emoji: "🇹🇨", category: 8, name: "flag: Turks & Caicos Islands", version: "2.0" }, { emoji: "🇹🇩", category: 8, name: "flag: Chad", version: "2.0" }, { emoji: "🇹🇫", category: 8, name: "flag: French Southern Territories", version: "2.0" }, { emoji: "🇹🇬", category: 8, name: "flag: Togo", version: "2.0" }, { emoji: "🇹ðŸ‡", category: 8, name: "flag: Thailand", version: "2.0" }, { emoji: "🇹🇯", category: 8, name: "flag: Tajikistan", version: "2.0" }, { emoji: "🇹🇰", category: 8, name: "flag: Tokelau", version: "2.0" }, { emoji: "🇹🇱", category: 8, name: "flag: Timor-Leste", version: "2.0" }, { emoji: "🇹🇲", category: 8, name: "flag: Turkmenistan", version: "2.0" }, { emoji: "🇹🇳", category: 8, name: "flag: Tunisia", version: "2.0" }, { emoji: "🇹🇴", category: 8, name: "flag: Tonga", version: "2.0" }, { emoji: "🇹🇷", category: 8, name: "flag: Turkey", version: "2.0" }, { emoji: "🇹🇹", category: 8, name: "flag: Trinidad & Tobago", version: "2.0" }, { emoji: "🇹🇻", category: 8, name: "flag: Tuvalu", version: "2.0" }, { emoji: "🇹🇼", category: 8, name: "flag: Taiwan", version: "2.0" }, { emoji: "🇹🇿", category: 8, name: "flag: Tanzania", version: "2.0" }, { emoji: "🇺🇦", category: 8, name: "flag: Ukraine", version: "2.0" }, { emoji: "🇺🇬", category: 8, name: "flag: Uganda", version: "2.0" }, { emoji: "🇺🇲", category: 8, name: "flag: U.S. Outlying Islands", version: "2.0" }, { emoji: "🇺🇳", category: 8, name: "flag: United Nations", version: "4.0" }, { emoji: "🇺🇸", category: 8, name: "flag: United States", version: "1.0" }, { emoji: "🇺🇾", category: 8, name: "flag: Uruguay", version: "2.0" }, { emoji: "🇺🇿", category: 8, name: "flag: Uzbekistan", version: "2.0" }, { emoji: "🇻🇦", category: 8, name: "flag: Vatican City", version: "2.0" }, { emoji: "🇻🇨", category: 8, name: "flag: St. Vincent & Grenadines", version: "2.0" }, { emoji: "🇻🇪", category: 8, name: "flag: Venezuela", version: "2.0" }, { emoji: "🇻🇬", category: 8, name: "flag: British Virgin Islands", version: "2.0" }, { emoji: "🇻🇮", category: 8, name: "flag: U.S. Virgin Islands", version: "2.0" }, { emoji: "🇻🇳", category: 8, name: "flag: Vietnam", version: "2.0" }, { emoji: "🇻🇺", category: 8, name: "flag: Vanuatu", version: "2.0" }, { emoji: "🇼🇫", category: 8, name: "flag: Wallis & Futuna", version: "2.0" }, { emoji: "🇼🇸", category: 8, name: "flag: Samoa", version: "2.0" }, { emoji: "🇽🇰", category: 8, name: "flag: Kosovo", version: "2.0" }, { emoji: "🇾🇪", category: 8, name: "flag: Yemen", version: "2.0" }, { emoji: "🇾🇹", category: 8, name: "flag: Mayotte", version: "2.0" }, { emoji: "🇿🇦", category: 8, name: "flag: South Africa", version: "2.0" }, { emoji: "🇿🇲", category: 8, name: "flag: Zambia", version: "2.0" }, { emoji: "🇿🇼", category: 8, name: "flag: Zimbabwe", version: "2.0" }, { emoji: "ðŸ´ó §ó ¢ó ¥ó ®ó §ó ¿", category: 8, name: "flag: England", version: "5.0" }, { emoji: "ðŸ´ó §ó ¢ó ³ó £ó ´ó ¿", category: 8, name: "flag: Scotland", version: "5.0" }, { emoji: "ðŸ´ó §ó ¢ó ·ó ¬ó ³ó ¿", category: 8, name: "flag: Wales", version: "5.0" }] }; const Ce = "emoji-picker__emoji"; function Ee(e, o) { const n = document.createElement(e); return o && (n.className = o), n } function _e(e) { for (; e.firstChild;)e.removeChild(e.firstChild) } function ze(e, o) { e.dataset.loaded || (e.dataset.custom ? function (e) { const o = Ee("img", "emoji-picker__custom-emoji"); e.dataset.emoji && (o.src = e.dataset.emoji, e.innerText = "", e.appendChild(o)) }(e) : "twemoji" === o.style && function (e, o) { e.dataset.emoji && (e.innerHTML = ke.parse(e.dataset.emoji, o.twemojiOptions)) }(e, o), e.dataset.loaded = "true", e.style.opacity = "1") } class Oe { constructor(e, o) { this.events = e, this.options = o } render() { const e = Ee("div", "emoji-picker__preview"); return this.emoji = Ee("div", "emoji-picker__preview-emoji"), e.appendChild(this.emoji), this.name = Ee("div", "emoji-picker__preview-name"), e.appendChild(this.name), this.events.on("showPreview", (e => this.showPreview(e))), this.events.on("hidePreview", (() => this.hidePreview())), e } showPreview(e) { let o = e.emoji; e.custom ? o = `<img class="emoji-picker__custom-emoji" src="${e.emoji}">` : "twemoji" === this.options.style && (o = ke.parse(e.emoji, this.options.twemojiOptions)), this.emoji.innerHTML = o, this.name.innerHTML = e.name } hidePreview() { this.emoji.innerHTML = "", this.name.innerHTML = "" } } function Ie(e, o) { for (var n = 0; n < o.length; n++) { var i = o[n]; i.enumerable = i.enumerable || !1, i.configurable = !0, "value" in i && (i.writable = !0), Object.defineProperty(e, i.key, i) } } function Se(e, o, n) { return o in e ? Object.defineProperty(e, o, { value: n, enumerable: !0, configurable: !0, writable: !0 }) : e[o] = n, e } function Pe(e) { for (var o = 1; o < arguments.length; o++) { var n = null != arguments[o] ? arguments[o] : {}, i = Object.keys(n); "function" == typeof Object.getOwnPropertySymbols && (i = i.concat(Object.getOwnPropertySymbols(n).filter((function (e) { return Object.getOwnPropertyDescriptor(n, e).enumerable })))), i.forEach((function (o) { Se(e, o, n[o]) })) } return e } function Me(e, o) { return function (e) { if (Array.isArray(e)) return e }(e) || function (e, o) { var n = [], i = !0, a = !1, r = void 0; try { for (var t, s = e[Symbol.iterator](); !(i = (t = s.next()).done) && (n.push(t.value), !o || n.length !== o); i = !0); } catch (e) { a = !0, r = e } finally { try { i || null == s.return || s.return() } finally { if (a) throw r } } return n }(e, o) || function () { throw new TypeError("Invalid attempt to destructure non-iterable instance") }() } var Ae = function () { }, Le = {}, Te = {}, Ne = { mark: Ae, measure: Ae }; try { "undefined" != typeof window && (Le = window), "undefined" != typeof document && (Te = document), "undefined" != typeof MutationObserver && MutationObserver, "undefined" != typeof performance && (Ne = performance) } catch (e) { } var Fe = (Le.navigator || {}).userAgent, Be = void 0 === Fe ? "" : Fe, De = Le, Re = Te, qe = Ne, Ve = (De.document, !!Re.documentElement && !!Re.head && "function" == typeof Re.addEventListener && "function" == typeof Re.createElement), He = (~Be.indexOf("MSIE") || Be.indexOf("Trident/"), function () { try { } catch (e) { return !1 } }(), "group"), Ue = "primary", We = "secondary", Ke = De.FontAwesomeConfig || {}; if (Re && "function" == typeof Re.querySelector) { [["data-family-prefix", "familyPrefix"], ["data-replacement-class", "replacementClass"], ["data-auto-replace-svg", "autoReplaceSvg"], ["data-auto-add-css", "autoAddCss"], ["data-auto-a11y", "autoA11y"], ["data-search-pseudo-elements", "searchPseudoElements"], ["data-observe-mutations", "observeMutations"], ["data-mutate-approach", "mutateApproach"], ["data-keep-original-source", "keepOriginalSource"], ["data-measure-performance", "measurePerformance"], ["data-show-missing-icons", "showMissingIcons"]].forEach((function (e) { var o = Me(e, 2), n = o[0], i = o[1], a = function (e) { return "" === e || "false" !== e && ("true" === e || e) }(function (e) { var o = Re.querySelector("script[" + e + "]"); if (o) return o.getAttribute(e) }(n)); null != a && (Ke[i] = a) })) } var Je = Pe({}, { familyPrefix: "fa", replacementClass: "svg-inline--fa", autoReplaceSvg: !0, autoAddCss: !0, autoA11y: !0, searchPseudoElements: !1, observeMutations: !0, mutateApproach: "async", keepOriginalSource: !0, measurePerformance: !1, showMissingIcons: !0 }, Ke); Je.autoReplaceSvg || (Je.observeMutations = !1); var Ge = Pe({}, Je); De.FontAwesomeConfig = Ge; var Xe = De || {}; Xe.___FONT_AWESOME___ || (Xe.___FONT_AWESOME___ = {}), Xe.___FONT_AWESOME___.styles || (Xe.___FONT_AWESOME___.styles = {}), Xe.___FONT_AWESOME___.hooks || (Xe.___FONT_AWESOME___.hooks = {}), Xe.___FONT_AWESOME___.shims || (Xe.___FONT_AWESOME___.shims = []); var Ye = Xe.___FONT_AWESOME___, $e = []; Ve && ((Re.documentElement.doScroll ? /^loaded|^c/ : /^loaded|^i|^c/).test(Re.readyState) || Re.addEventListener("DOMContentLoaded", (function e() { Re.removeEventListener("DOMContentLoaded", e), 1, $e.map((function (e) { return e() })) }))); "undefined" != typeof global && void 0 !== global.process && global.process.emit, "undefined" == typeof setImmediate ? setTimeout : setImmediate; var Ze = { size: 16, x: 0, y: 0, rotate: 0, flipX: !1, flipY: !1 }; function Qe() { for (var e = 12, o = ""; e-- > 0;)o += "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"[62 * Math.random() | 0]; return o } function eo(e) { return "".concat(e).replace(/&/g, "&").replace(/"/g, """).replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">") } function oo(e) { return Object.keys(e || {}).reduce((function (o, n) { return o + "".concat(n, ": ").concat(e[n], ";") }), "") } function no(e) { return e.size !== Ze.size || e.x !== Ze.x || e.y !== Ze.y || e.rotate !== Ze.rotate || e.flipX || e.flipY } function io(e) { var o = e.transform, n = e.containerWidth, i = e.iconWidth, a = { transform: "translate(".concat(n / 2, " 256)") }, r = "translate(".concat(32 * o.x, ", ").concat(32 * o.y, ") "), t = "scale(".concat(o.size / 16 * (o.flipX ? -1 : 1), ", ").concat(o.size / 16 * (o.flipY ? -1 : 1), ") "), s = "rotate(".concat(o.rotate, " 0 0)"); return { outer: a, inner: { transform: "".concat(r, " ").concat(t, " ").concat(s) }, path: { transform: "translate(".concat(i / 2 * -1, " -256)") } } } var ao = { x: 0, y: 0, width: "100%", height: "100%" }; function ro(e) { var o = !(arguments.length > 1 && void 0 !== arguments[1]) || arguments[1]; return e.attributes && (e.attributes.fill || o) && (e.attributes.fill = "black"), e } function to(e) { var o = e.icons, n = o.main, i = o.mask, a = e.prefix, r = e.iconName, t = e.transform, s = e.symbol, m = e.title, c = e.maskId, d = e.titleId, g = e.extra, u = e.watchable, l = void 0 !== u && u, v = i.found ? i : n, f = v.width, y = v.height, j = "fa-w-".concat(Math.ceil(f / y * 16)), h = [Ge.replacementClass, r ? "".concat(Ge.familyPrefix, "-").concat(r) : "", j].filter((function (e) { return -1 === g.classes.indexOf(e) })).concat(g.classes).join(" "), p = { children: [], attributes: Pe({}, g.attributes, { "data-prefix": a, "data-icon": r, class: h, role: g.attributes.role || "img", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 ".concat(f, " ").concat(y) }) }; l && (p.attributes["data-fa-i2svg"] = ""), m && p.children.push({ tag: "title", attributes: { id: p.attributes["aria-labelledby"] || "title-".concat(d || Qe()) }, children: [m] }); var b = Pe({}, p, { prefix: a, iconName: r, main: n, mask: i, maskId: c, transform: t, symbol: s, styles: g.styles }), w = i.found && n.found ? function (e) { var o, n = e.children, i = e.attributes, a = e.main, r = e.mask, t = e.maskId, s = e.transform, m = a.width, c = a.icon, d = r.width, g = r.icon, u = io({ transform: s, containerWidth: d, iconWidth: m }), l = { tag: "rect", attributes: Pe({}, ao, { fill: "white" }) }, v = c.children ? { children: c.children.map(ro) } : {}, f = { tag: "g", attributes: Pe({}, u.inner), children: [ro(Pe({ tag: c.tag, attributes: Pe({}, c.attributes, u.path) }, v))] }, y = { tag: "g", attributes: Pe({}, u.outer), children: [f] }, j = "mask-".concat(t || Qe()), h = "clip-".concat(t || Qe()), p = { tag: "mask", attributes: Pe({}, ao, { id: j, maskUnits: "userSpaceOnUse", maskContentUnits: "userSpaceOnUse" }), children: [l, y] }, b = { tag: "defs", children: [{ tag: "clipPath", attributes: { id: h }, children: (o = g, "g" === o.tag ? o.children : [o]) }, p] }; return n.push(b, { tag: "rect", attributes: Pe({ fill: "currentColor", "clip-path": "url(#".concat(h, ")"), mask: "url(#".concat(j, ")") }, ao) }), { children: n, attributes: i } }(b) : function (e) { var o = e.children, n = e.attributes, i = e.main, a = e.transform, r = oo(e.styles); if (r.length > 0 && (n.style = r), no(a)) { var t = io({ transform: a, containerWidth: i.width, iconWidth: i.width }); o.push({ tag: "g", attributes: Pe({}, t.outer), children: [{ tag: "g", attributes: Pe({}, t.inner), children: [{ tag: i.icon.tag, children: i.icon.children, attributes: Pe({}, i.icon.attributes, t.path) }] }] }) } else o.push(i.icon); return { children: o, attributes: n } }(b), k = w.children, x = w.attributes; return b.children = k, b.attributes = x, s ? function (e) { var o = e.prefix, n = e.iconName, i = e.children, a = e.attributes, r = e.symbol; return [{ tag: "svg", attributes: { style: "display: none;" }, children: [{ tag: "symbol", attributes: Pe({}, a, { id: !0 === r ? "".concat(o, "-").concat(Ge.familyPrefix, "-").concat(n) : r }), children: i }] }] }(b) : function (e) { var o = e.children, n = e.main, i = e.mask, a = e.attributes, r = e.styles, t = e.transform; if (no(t) && n.found && !i.found) { var s = { x: n.width / n.height / 2, y: .5 }; a.style = oo(Pe({}, r, { "transform-origin": "".concat(s.x + t.x / 16, "em ").concat(s.y + t.y / 16, "em") })) } return [{ tag: "svg", attributes: a, children: o }] }(b) } var so = function () { }, mo = (Ge.measurePerformance && qe && qe.mark && qe.measure, function (e, o, n, i) { var a, r, t, s = Object.keys(e), m = s.length, c = void 0 !== i ? function (e, o) { return function (n, i, a, r) { return e.call(o, n, i, a, r) } }(o, i) : o; for (void 0 === n ? (a = 1, t = e[s[0]]) : (a = 0, t = n); a < m; a++)t = c(t, e[r = s[a]], r, e); return t }); function co(e, o) { var n = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : {}, i = n.skipHooks, a = void 0 !== i && i, r = Object.keys(o).reduce((function (e, n) { var i = o[n]; return !!i.icon ? e[i.iconName] = i.icon : e[n] = i, e }), {}); "function" != typeof Ye.hooks.addPack || a ? Ye.styles[e] = Pe({}, Ye.styles[e] || {}, r) : Ye.hooks.addPack(e, r), "fas" === e && co("fa", o) } var go = Ye.styles, uo = Ye.shims, lo = function () { var e = function (e) { return mo(go, (function (o, n, i) { return o[i] = mo(n, e, {}), o }), {}) }; e((function (e, o, n) { return o[3] && (e[o[3]] = n), e })), e((function (e, o, n) { var i = o[2]; return e[n] = n, i.forEach((function (o) { e[o] = n })), e })); var o = "far" in go; mo(uo, (function (e, n) { var i = n[0], a = n[1], r = n[2]; return "far" !== a || o || (a = "fas"), e[i] = { prefix: a, iconName: r }, e }), {}) }; lo(); Ye.styles; function vo(e, o, n) { if (e && e[o] && e[o][n]) return { prefix: o, iconName: n, icon: e[o][n] } } function fo(e) { var o = e.tag, n = e.attributes, i = void 0 === n ? {} : n, a = e.children, r = void 0 === a ? [] : a; return "string" == typeof e ? eo(e) : "<".concat(o, " ").concat(function (e) { return Object.keys(e || {}).reduce((function (o, n) { return o + "".concat(n, '="').concat(eo(e[n]), '" ') }), "").trim() }(i), ">").concat(r.map(fo).join(""), "</").concat(o, ">") } function yo(e) { this.name = "MissingIcon", this.message = e || "Icon unavailable", this.stack = (new Error).stack } yo.prototype = Object.create(Error.prototype), yo.prototype.constructor = yo; var jo = { fill: "currentColor" }, ho = { attributeType: "XML", repeatCount: "indefinite", dur: "2s" }, po = (Pe({}, jo, { d: "M156.5,447.7l-12.6,29.5c-18.7-9.5-35.9-21.2-51.5-34.9l22.7-22.7C127.6,430.5,141.5,440,156.5,447.7z M40.6,272H8.5 c1.4,21.2,5.4,41.7,11.7,61.1L50,321.2C45.1,305.5,41.8,289,40.6,272z M40.6,240c1.4-18.8,5.2-37,11.1-54.1l-29.5-12.6 C14.7,194.3,10,216.7,8.5,240H40.6z M64.3,156.5c7.8-14.9,17.2-28.8,28.1-41.5L69.7,92.3c-13.7,15.6-25.5,32.8-34.9,51.5 L64.3,156.5z M397,419.6c-13.9,12-29.4,22.3-46.1,30.4l11.9,29.8c20.7-9.9,39.8-22.6,56.9-37.6L397,419.6z M115,92.4 c13.9-12,29.4-22.3,46.1-30.4l-11.9-29.8c-20.7,9.9-39.8,22.6-56.8,37.6L115,92.4z M447.7,355.5c-7.8,14.9-17.2,28.8-28.1,41.5 l22.7,22.7c13.7-15.6,25.5-32.9,34.9-51.5L447.7,355.5z M471.4,272c-1.4,18.8-5.2,37-11.1,54.1l29.5,12.6 c7.5-21.1,12.2-43.5,13.6-66.8H471.4z M321.2,462c-15.7,5-32.2,8.2-49.2,9.4v32.1c21.2-1.4,41.7-5.4,61.1-11.7L321.2,462z M240,471.4c-18.8-1.4-37-5.2-54.1-11.1l-12.6,29.5c21.1,7.5,43.5,12.2,66.8,13.6V471.4z M462,190.8c5,15.7,8.2,32.2,9.4,49.2h32.1 c-1.4-21.2-5.4-41.7-11.7-61.1L462,190.8z M92.4,397c-12-13.9-22.3-29.4-30.4-46.1l-29.8,11.9c9.9,20.7,22.6,39.8,37.6,56.9 L92.4,397z M272,40.6c18.8,1.4,36.9,5.2,54.1,11.1l12.6-29.5C317.7,14.7,295.3,10,272,8.5V40.6z M190.8,50 c15.7-5,32.2-8.2,49.2-9.4V8.5c-21.2,1.4-41.7,5.4-61.1,11.7L190.8,50z M442.3,92.3L419.6,115c12,13.9,22.3,29.4,30.5,46.1 l29.8-11.9C470,128.5,457.3,109.4,442.3,92.3z M397,92.4l22.7-22.7c-15.6-13.7-32.8-25.5-51.5-34.9l-12.6,29.5 C370.4,72.1,384.4,81.5,397,92.4z" }), Pe({}, ho, { attributeName: "opacity" })); Pe({}, jo, { cx: "256", cy: "364", r: "28" }), Pe({}, ho, { attributeName: "r", values: "28;14;28;28;14;28;" }), Pe({}, po, { values: "1;0;1;1;0;1;" }), Pe({}, jo, { opacity: "1", d: "M263.7,312h-16c-6.6,0-12-5.4-12-12c0-71,77.4-63.9,77.4-107.8c0-20-17.8-40.2-57.4-40.2c-29.1,0-44.3,9.6-59.2,28.7 c-3.9,5-11.1,6-16.2,2.4l-13.1-9.2c-5.6-3.9-6.9-11.8-2.6-17.2c21.2-27.2,46.4-44.7,91.2-44.7c52.3,0,97.4,29.8,97.4,80.2 c0,67.6-77.4,63.5-77.4,107.8C275.7,306.6,270.3,312,263.7,312z" }), Pe({}, po, { values: "1;0;0;0;0;1;" }), Pe({}, jo, { opacity: "0", d: "M232.5,134.5l7,168c0.3,6.4,5.6,11.5,12,11.5h9c6.4,0,11.7-5.1,12-11.5l7-168c0.3-6.8-5.2-12.5-12-12.5h-23 C237.7,122,232.2,127.7,232.5,134.5z" }), Pe({}, po, { values: "0;0;1;1;0;0;" }), Ye.styles; function bo(e) { var o = e[0], n = e[1], i = Me(e.slice(4), 1)[0]; return { found: !0, width: o, height: n, icon: Array.isArray(i) ? { tag: "g", attributes: { class: "".concat(Ge.familyPrefix, "-").concat(He) }, children: [{ tag: "path", attributes: { class: "".concat(Ge.familyPrefix, "-").concat(We), fill: "currentColor", d: i[0] } }, { tag: "path", attributes: { class: "".concat(Ge.familyPrefix, "-").concat(Ue), fill: "currentColor", d: i[1] } }] } : { tag: "path", attributes: { fill: "currentColor", d: i } } } } Ye.styles; function wo() { Ge.autoAddCss && !_o && (!function (e) { if (e && Ve) { var o = Re.createElement("style"); o.setAttribute("type", "text/css"), o.innerHTML = e; for (var n = Re.head.childNodes, i = null, a = n.length - 1; a > -1; a--) { var r = n[a], t = (r.tagName || "").toUpperCase();["STYLE", "LINK"].indexOf(t) > -1 && (i = r) } Re.head.insertBefore(o, i) } }(function () { var e = "fa", o = "svg-inline--fa", n = Ge.familyPrefix, i = Ge.replacementClass, a = 'svg:not(:root).svg-inline--fa {\n overflow: visible;\n}\n\n.svg-inline--fa {\n display: inline-block;\n font-size: inherit;\n height: 1em;\n overflow: visible;\n vertical-align: -0.125em;\n}\n.svg-inline--fa.fa-lg {\n vertical-align: -0.225em;\n}\n.svg-inline--fa.fa-w-1 {\n width: 0.0625em;\n}\n.svg-inline--fa.fa-w-2 {\n width: 0.125em;\n}\n.svg-inline--fa.fa-w-3 {\n width: 0.1875em;\n}\n.svg-inline--fa.fa-w-4 {\n width: 0.25em;\n}\n.svg-inline--fa.fa-w-5 {\n width: 0.3125em;\n}\n.svg-inline--fa.fa-w-6 {\n width: 0.375em;\n}\n.svg-inline--fa.fa-w-7 {\n width: 0.4375em;\n}\n.svg-inline--fa.fa-w-8 {\n width: 0.5em;\n}\n.svg-inline--fa.fa-w-9 {\n width: 0.5625em;\n}\n.svg-inline--fa.fa-w-10 {\n width: 0.625em;\n}\n.svg-inline--fa.fa-w-11 {\n width: 0.6875em;\n}\n.svg-inline--fa.fa-w-12 {\n width: 0.75em;\n}\n.svg-inline--fa.fa-w-13 {\n width: 0.8125em;\n}\n.svg-inline--fa.fa-w-14 {\n width: 0.875em;\n}\n.svg-inline--fa.fa-w-15 {\n width: 0.9375em;\n}\n.svg-inline--fa.fa-w-16 {\n width: 1em;\n}\n.svg-inline--fa.fa-w-17 {\n width: 1.0625em;\n}\n.svg-inline--fa.fa-w-18 {\n width: 1.125em;\n}\n.svg-inline--fa.fa-w-19 {\n width: 1.1875em;\n}\n.svg-inline--fa.fa-w-20 {\n width: 1.25em;\n}\n.svg-inline--fa.fa-pull-left {\n margin-right: 0.3em;\n width: auto;\n}\n.svg-inline--fa.fa-pull-right {\n margin-left: 0.3em;\n width: auto;\n}\n.svg-inline--fa.fa-border {\n height: 1.5em;\n}\n.svg-inline--fa.fa-li {\n width: 2em;\n}\n.svg-inline--fa.fa-fw {\n width: 1.25em;\n}\n\n.fa-layers svg.svg-inline--fa {\n bottom: 0;\n left: 0;\n margin: auto;\n position: absolute;\n right: 0;\n top: 0;\n}\n\n.fa-layers {\n display: inline-block;\n height: 1em;\n position: relative;\n text-align: center;\n vertical-align: -0.125em;\n width: 1em;\n}\n.fa-layers svg.svg-inline--fa {\n -webkit-transform-origin: center center;\n transform-origin: center center;\n}\n\n.fa-layers-counter, .fa-layers-text {\n display: inline-block;\n position: absolute;\n text-align: center;\n}\n\n.fa-layers-text {\n left: 50%;\n top: 50%;\n -webkit-transform: translate(-50%, -50%);\n transform: translate(-50%, -50%);\n -webkit-transform-origin: center center;\n transform-origin: center center;\n}\n\n.fa-layers-counter {\n background-color: #ff253a;\n border-radius: 1em;\n -webkit-box-sizing: border-box;\n box-sizing: border-box;\n color: #fff;\n height: 1.5em;\n line-height: 1;\n max-width: 5em;\n min-width: 1.5em;\n overflow: hidden;\n padding: 0.25em;\n right: 0;\n text-overflow: ellipsis;\n top: 0;\n -webkit-transform: scale(0.25);\n transform: scale(0.25);\n -webkit-transform-origin: top right;\n transform-origin: top right;\n}\n\n.fa-layers-bottom-right {\n bottom: 0;\n right: 0;\n top: auto;\n -webkit-transform: scale(0.25);\n transform: scale(0.25);\n -webkit-transform-origin: bottom right;\n transform-origin: bottom right;\n}\n\n.fa-layers-bottom-left {\n bottom: 0;\n left: 0;\n right: auto;\n top: auto;\n -webkit-transform: scale(0.25);\n transform: scale(0.25);\n -webkit-transform-origin: bottom left;\n transform-origin: bottom left;\n}\n\n.fa-layers-top-right {\n right: 0;\n top: 0;\n -webkit-transform: scale(0.25);\n transform: scale(0.25);\n -webkit-transform-origin: top right;\n transform-origin: top right;\n}\n\n.fa-layers-top-left {\n left: 0;\n right: auto;\n top: 0;\n -webkit-transform: scale(0.25);\n transform: scale(0.25);\n -webkit-transform-origin: top left;\n transform-origin: top left;\n}\n\n.fa-lg {\n font-size: 1.3333333333em;\n line-height: 0.75em;\n vertical-align: -0.0667em;\n}\n\n.fa-xs {\n font-size: 0.75em;\n}\n\n.fa-sm {\n font-size: 0.875em;\n}\n\n.fa-1x {\n font-size: 1em;\n}\n\n.fa-2x {\n font-size: 2em;\n}\n\n.fa-3x {\n font-size: 3em;\n}\n\n.fa-4x {\n font-size: 4em;\n}\n\n.fa-5x {\n font-size: 5em;\n}\n\n.fa-6x {\n font-size: 6em;\n}\n\n.fa-7x {\n font-size: 7em;\n}\n\n.fa-8x {\n font-size: 8em;\n}\n\n.fa-9x {\n font-size: 9em;\n}\n\n.fa-10x {\n font-size: 10em;\n}\n\n.fa-fw {\n text-align: center;\n width: 1.25em;\n}\n\n.fa-ul {\n list-style-type: none;\n margin-left: 2.5em;\n padding-left: 0;\n}\n.fa-ul > li {\n position: relative;\n}\n\n.fa-li {\n left: -2em;\n position: absolute;\n text-align: center;\n width: 2em;\n line-height: inherit;\n}\n\n.fa-border {\n border: solid 0.08em #eee;\n border-radius: 0.1em;\n padding: 0.2em 0.25em 0.15em;\n}\n\n.fa-pull-left {\n float: left;\n}\n\n.fa-pull-right {\n float: right;\n}\n\n.fa.fa-pull-left,\n.fas.fa-pull-left,\n.far.fa-pull-left,\n.fal.fa-pull-left,\n.fab.fa-pull-left {\n margin-right: 0.3em;\n}\n.fa.fa-pull-right,\n.fas.fa-pull-right,\n.far.fa-pull-right,\n.fal.fa-pull-right,\n.fab.fa-pull-right {\n margin-left: 0.3em;\n}\n\n.fa-spin {\n -webkit-animation: fa-spin 2s infinite linear;\n animation: fa-spin 2s infinite linear;\n}\n\n.fa-pulse {\n -webkit-animation: fa-spin 1s infinite steps(8);\n animation: fa-spin 1s infinite steps(8);\n}\n\n@-webkit-keyframes fa-spin {\n 0% {\n -webkit-transform: rotate(0deg);\n transform: rotate(0deg);\n }\n 100% {\n -webkit-transform: rotate(360deg);\n transform: rotate(360deg);\n }\n}\n\n@keyframes fa-spin {\n 0% {\n -webkit-transform: rotate(0deg);\n transform: rotate(0deg);\n }\n 100% {\n -webkit-transform: rotate(360deg);\n transform: rotate(360deg);\n }\n}\n.fa-rotate-90 {\n -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";\n -webkit-transform: rotate(90deg);\n transform: rotate(90deg);\n}\n\n.fa-rotate-180 {\n -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";\n -webkit-transform: rotate(180deg);\n transform: rotate(180deg);\n}\n\n.fa-rotate-270 {\n -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";\n -webkit-transform: rotate(270deg);\n transform: rotate(270deg);\n}\n\n.fa-flip-horizontal {\n -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";\n -webkit-transform: scale(-1, 1);\n transform: scale(-1, 1);\n}\n\n.fa-flip-vertical {\n -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";\n -webkit-transform: scale(1, -1);\n transform: scale(1, -1);\n}\n\n.fa-flip-both, .fa-flip-horizontal.fa-flip-vertical {\n -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";\n -webkit-transform: scale(-1, -1);\n transform: scale(-1, -1);\n}\n\n:root .fa-rotate-90,\n:root .fa-rotate-180,\n:root .fa-rotate-270,\n:root .fa-flip-horizontal,\n:root .fa-flip-vertical,\n:root .fa-flip-both {\n -webkit-filter: none;\n filter: none;\n}\n\n.fa-stack {\n display: inline-block;\n height: 2em;\n position: relative;\n width: 2.5em;\n}\n\n.fa-stack-1x,\n.fa-stack-2x {\n bottom: 0;\n left: 0;\n margin: auto;\n position: absolute;\n right: 0;\n top: 0;\n}\n\n.svg-inline--fa.fa-stack-1x {\n height: 1em;\n width: 1.25em;\n}\n.svg-inline--fa.fa-stack-2x {\n height: 2em;\n width: 2.5em;\n}\n\n.fa-inverse {\n color: #fff;\n}\n\n.sr-only {\n border: 0;\n clip: rect(0, 0, 0, 0);\n height: 1px;\n margin: -1px;\n overflow: hidden;\n padding: 0;\n position: absolute;\n width: 1px;\n}\n\n.sr-only-focusable:active, .sr-only-focusable:focus {\n clip: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n position: static;\n width: auto;\n}\n\n.svg-inline--fa .fa-primary {\n fill: var(--fa-primary-color, currentColor);\n opacity: 1;\n opacity: var(--fa-primary-opacity, 1);\n}\n\n.svg-inline--fa .fa-secondary {\n fill: var(--fa-secondary-color, currentColor);\n opacity: 0.4;\n opacity: var(--fa-secondary-opacity, 0.4);\n}\n\n.svg-inline--fa.fa-swap-opacity .fa-primary {\n opacity: 0.4;\n opacity: var(--fa-secondary-opacity, 0.4);\n}\n\n.svg-inline--fa.fa-swap-opacity .fa-secondary {\n opacity: 1;\n opacity: var(--fa-primary-opacity, 1);\n}\n\n.svg-inline--fa mask .fa-primary,\n.svg-inline--fa mask .fa-secondary {\n fill: black;\n}\n\n.fad.fa-inverse {\n color: #fff;\n}'; if (n !== e || i !== o) { var r = new RegExp("\\.".concat(e, "\\-"), "g"), t = new RegExp("\\--".concat(e, "\\-"), "g"), s = new RegExp("\\.".concat(o), "g"); a = a.replace(r, ".".concat(n, "-")).replace(t, "--".concat(n, "-")).replace(s, ".".concat(i)) } return a }()), _o = !0) } function ko(e, o) { return Object.defineProperty(e, "abstract", { get: o }), Object.defineProperty(e, "html", { get: function () { return e.abstract.map((function (e) { return fo(e) })) } }), Object.defineProperty(e, "node", { get: function () { if (Ve) { var o = Re.createElement("div"); return o.innerHTML = e.html, o.children } } }), e } function xo(e) { var o = e.prefix, n = void 0 === o ? "fa" : o, i = e.iconName; if (i) return vo(Eo.definitions, n, i) || vo(Ye.styles, n, i) } var Co, Eo = new (function () { function e() { !function (e, o) { if (!(e instanceof o)) throw new TypeError("Cannot call a class as a function") }(this, e), this.definitions = {} } var o, n, i; return o = e, (n = [{ key: "add", value: function () { for (var e = this, o = arguments.length, n = new Array(o), i = 0; i < o; i++)n[i] = arguments[i]; var a = n.reduce(this._pullDefinitions, {}); Object.keys(a).forEach((function (o) { e.definitions[o] = Pe({}, e.definitions[o] || {}, a[o]), co(o, a[o]), lo() })) } }, { key: "reset", value: function () { this.definitions = {} } }, { key: "_pullDefinitions", value: function (e, o) { var n = o.prefix && o.iconName && o.icon ? { 0: o } : o; return Object.keys(n).map((function (o) { var i = n[o], a = i.prefix, r = i.iconName, t = i.icon; e[a] || (e[a] = {}), e[a][r] = t })), e } }]) && Ie(o.prototype, n), i && Ie(o, i), e }()), _o = !1, zo = (Co = function (e) { var o = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {}, n = o.transform, i = void 0 === n ? Ze : n, a = o.symbol, r = void 0 !== a && a, t = o.mask, s = void 0 === t ? null : t, m = o.maskId, c = void 0 === m ? null : m, d = o.title, g = void 0 === d ? null : d, u = o.titleId, l = void 0 === u ? null : u, v = o.classes, f = void 0 === v ? [] : v, y = o.attributes, j = void 0 === y ? {} : y, h = o.styles, p = void 0 === h ? {} : h; if (e) { var b = e.prefix, w = e.iconName, k = e.icon; return ko(Pe({ type: "icon" }, e), (function () { return wo(), Ge.autoA11y && (g ? j["aria-labelledby"] = "".concat(Ge.replacementClass, "-title-").concat(l || Qe()) : (j["aria-hidden"] = "true", j.focusable = "false")), to({ icons: { main: bo(k), mask: s ? bo(s.icon) : { found: !1, width: null, height: null, icon: {} } }, prefix: b, iconName: w, transform: Pe({}, Ze, i), symbol: r, title: g, maskId: c, titleId: l, extra: { attributes: j, styles: p, classes: f } }) })) } }, function (e) { var o = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {}, n = (e || {}).icon ? e : xo(e || {}), i = o.mask; return i && (i = (i || {}).icon ? i : xo(i || {})), Co(n, Pe({}, o, { mask: i })) }); Eo.add({ prefix: "far", iconName: "building", icon: [448, 512, [], "f1ad", "M128 148v-40c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12h-40c-6.6 0-12-5.4-12-12zm140 12h40c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12zm-128 96h40c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12zm128 0h40c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12zm-76 84v-40c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h40c6.6 0 12-5.4 12-12zm76 12h40c6.6 0 12-5.4 12-12v-40c0-6.6-5.4-12-12-12h-40c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12zm180 124v36H0v-36c0-6.6 5.4-12 12-12h19.5V24c0-13.3 10.7-24 24-24h337c13.3 0 24 10.7 24 24v440H436c6.6 0 12 5.4 12 12zM79.5 463H192v-67c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v67h112.5V49L80 48l-.5 415z"] }, { prefix: "fas", iconName: "cat", icon: [512, 512, [], "f6be", "M290.59 192c-20.18 0-106.82 1.98-162.59 85.95V192c0-52.94-43.06-96-96-96-17.67 0-32 14.33-32 32s14.33 32 32 32c17.64 0 32 14.36 32 32v256c0 35.3 28.7 64 64 64h176c8.84 0 16-7.16 16-16v-16c0-17.67-14.33-32-32-32h-32l128-96v144c0 8.84 7.16 16 16 16h32c8.84 0 16-7.16 16-16V289.86c-10.29 2.67-20.89 4.54-32 4.54-61.81 0-113.52-44.05-125.41-102.4zM448 96h-64l-64-64v134.4c0 53.02 42.98 96 96 96s96-42.98 96-96V32l-64 64zm-72 80c-8.84 0-16-7.16-16-16s7.16-16 16-16 16 7.16 16 16-7.16 16-16 16zm80 0c-8.84 0-16-7.16-16-16s7.16-16 16-16 16 7.16 16 16-7.16 16-16 16z"] }, { prefix: "fas", iconName: "coffee", icon: [640, 512, [], "f0f4", "M192 384h192c53 0 96-43 96-96h32c70.6 0 128-57.4 128-128S582.6 32 512 32H120c-13.3 0-24 10.7-24 24v232c0 53 43 96 96 96zM512 96c35.3 0 64 28.7 64 64s-28.7 64-64 64h-32V96h32zm47.7 384H48.3c-47.6 0-61-64-36-64h583.3c25 0 11.8 64-35.9 64z"] }, { prefix: "far", iconName: "flag", icon: [512, 512, [], "f024", "M336.174 80c-49.132 0-93.305-32-161.913-32-31.301 0-58.303 6.482-80.721 15.168a48.04 48.04 0 0 0 2.142-20.727C93.067 19.575 74.167 1.594 51.201.104 23.242-1.71 0 20.431 0 48c0 17.764 9.657 33.262 24 41.562V496c0 8.837 7.163 16 16 16h16c8.837 0 16-7.163 16-16v-83.443C109.869 395.28 143.259 384 199.826 384c49.132 0 93.305 32 161.913 32 58.479 0 101.972-22.617 128.548-39.981C503.846 367.161 512 352.051 512 335.855V95.937c0-34.459-35.264-57.768-66.904-44.117C409.193 67.309 371.641 80 336.174 80zM464 336c-21.783 15.412-60.824 32-102.261 32-59.945 0-102.002-32-161.913-32-43.361 0-96.379 9.403-127.826 24V128c21.784-15.412 60.824-32 102.261-32 59.945 0 102.002 32 161.913 32 43.271 0 96.32-17.366 127.826-32v240z"] }, { prefix: "far", iconName: "frown", icon: [496, 512, [], "f119", "M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160-64c-17.7 0-32 14.3-32 32s14.3 32 32 32 32-14.3 32-32-14.3-32-32-32zm-80 128c-40.2 0-78 17.7-103.8 48.6-8.5 10.2-7.1 25.3 3.1 33.8 10.2 8.4 25.3 7.1 33.8-3.1 16.6-19.9 41-31.4 66.9-31.4s50.3 11.4 66.9 31.4c8.1 9.7 23.1 11.9 33.8 3.1 10.2-8.5 11.5-23.6 3.1-33.8C326 321.7 288.2 304 248 304z"] }, { prefix: "fas", iconName: "futbol", icon: [512, 512, [], "f1e3", "M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zm-48 0l-.003-.282-26.064 22.741-62.679-58.5 16.454-84.355 34.303 3.072c-24.889-34.216-60.004-60.089-100.709-73.141l13.651 31.939L256 139l-74.953-41.525 13.651-31.939c-40.631 13.028-75.78 38.87-100.709 73.141l34.565-3.073 16.192 84.355-62.678 58.5-26.064-22.741-.003.282c0 43.015 13.497 83.952 38.472 117.991l7.704-33.897 85.138 10.447 36.301 77.826-29.902 17.786c40.202 13.122 84.29 13.148 124.572 0l-29.902-17.786 36.301-77.826 85.138-10.447 7.704 33.897C442.503 339.952 456 299.015 456 256zm-248.102 69.571l-29.894-91.312L256 177.732l77.996 56.527-29.622 91.312h-96.476z"] }, { prefix: "fas", iconName: "history", icon: [512, 512, [], "f1da", "M504 255.531c.253 136.64-111.18 248.372-247.82 248.468-59.015.042-113.223-20.53-155.822-54.911-11.077-8.94-11.905-25.541-1.839-35.607l11.267-11.267c8.609-8.609 22.353-9.551 31.891-1.984C173.062 425.135 212.781 440 256 440c101.705 0 184-82.311 184-184 0-101.705-82.311-184-184-184-48.814 0-93.149 18.969-126.068 49.932l50.754 50.754c10.08 10.08 2.941 27.314-11.313 27.314H24c-8.837 0-16-7.163-16-16V38.627c0-14.254 17.234-21.393 27.314-11.314l49.372 49.372C129.209 34.136 189.552 8 256 8c136.81 0 247.747 110.78 248 247.531zm-180.912 78.784l9.823-12.63c8.138-10.463 6.253-25.542-4.21-33.679L288 256.349V152c0-13.255-10.745-24-24-24h-16c-13.255 0-24 10.745-24 24v135.651l65.409 50.874c10.463 8.137 25.541 6.253 33.679-4.21z"] }, { prefix: "fas", iconName: "icons", icon: [512, 512, [], "f86d", "M116.65 219.35a15.68 15.68 0 0 0 22.65 0l96.75-99.83c28.15-29 26.5-77.1-4.91-103.88C203.75-7.7 163-3.5 137.86 22.44L128 32.58l-9.85-10.14C93.05-3.5 52.25-7.7 24.86 15.64c-31.41 26.78-33 74.85-5 103.88zm143.92 100.49h-48l-7.08-14.24a27.39 27.39 0 0 0-25.66-17.78h-71.71a27.39 27.39 0 0 0-25.66 17.78l-7 14.24h-48A27.45 27.45 0 0 0 0 347.3v137.25A27.44 27.44 0 0 0 27.43 512h233.14A27.45 27.45 0 0 0 288 484.55V347.3a27.45 27.45 0 0 0-27.43-27.46zM144 468a52 52 0 1 1 52-52 52 52 0 0 1-52 52zm355.4-115.9h-60.58l22.36-50.75c2.1-6.65-3.93-13.21-12.18-13.21h-75.59c-6.3 0-11.66 3.9-12.5 9.1l-16.8 106.93c-1 6.3 4.88 11.89 12.5 11.89h62.31l-24.2 83c-1.89 6.65 4.2 12.9 12.23 12.9a13.26 13.26 0 0 0 10.92-5.25l92.4-138.91c4.88-6.91-1.16-15.7-10.87-15.7zM478.08.33L329.51 23.17C314.87 25.42 304 38.92 304 54.83V161.6a83.25 83.25 0 0 0-16-1.7c-35.35 0-64 21.48-64 48s28.65 48 64 48c35.2 0 63.73-21.32 64-47.66V99.66l112-17.22v47.18a83.25 83.25 0 0 0-16-1.7c-35.35 0-64 21.48-64 48s28.65 48 64 48c35.2 0 63.73-21.32 64-47.66V32c0-19.48-16-34.42-33.92-31.67z"] }, { prefix: "far", iconName: "lightbulb", icon: [352, 512, [], "f0eb", "M176 80c-52.94 0-96 43.06-96 96 0 8.84 7.16 16 16 16s16-7.16 16-16c0-35.3 28.72-64 64-64 8.84 0 16-7.16 16-16s-7.16-16-16-16zM96.06 459.17c0 3.15.93 6.22 2.68 8.84l24.51 36.84c2.97 4.46 7.97 7.14 13.32 7.14h78.85c5.36 0 10.36-2.68 13.32-7.14l24.51-36.84c1.74-2.62 2.67-5.7 2.68-8.84l.05-43.18H96.02l.04 43.18zM176 0C73.72 0 0 82.97 0 176c0 44.37 16.45 84.85 43.56 115.78 16.64 18.99 42.74 58.8 52.42 92.16v.06h48v-.12c-.01-4.77-.72-9.51-2.15-14.07-5.59-17.81-22.82-64.77-62.17-109.67-20.54-23.43-31.52-53.15-31.61-84.14-.2-73.64 59.67-128 127.95-128 70.58 0 128 57.42 128 128 0 30.97-11.24 60.85-31.65 84.14-39.11 44.61-56.42 91.47-62.1 109.46a47.507 47.507 0 0 0-2.22 14.3v.1h48v-.05c9.68-33.37 35.78-73.18 52.42-92.16C335.55 260.85 352 220.37 352 176 352 78.8 273.2 0 176 0z"] }, { prefix: "fas", iconName: "music", icon: [512, 512, [], "f001", "M470.38 1.51L150.41 96A32 32 0 0 0 128 126.51v261.41A139 139 0 0 0 96 384c-53 0-96 28.66-96 64s43 64 96 64 96-28.66 96-64V214.32l256-75v184.61a138.4 138.4 0 0 0-32-3.93c-53 0-96 28.66-96 64s43 64 96 64 96-28.65 96-64V32a32 32 0 0 0-41.62-30.49z"] }, { prefix: "fas", iconName: "search", icon: [512, 512, [], "f002", "M505 442.7L405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c48.3 0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9 0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7 0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7 0 128 57.2 128 128 0 70.7-57.2 128-128 128z"] }, { prefix: "far", iconName: "smile", icon: [496, 512, [], "f118", "M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160 0c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm4 72.6c-20.8 25-51.5 39.4-84 39.4s-63.2-14.3-84-39.4c-8.5-10.2-23.7-11.5-33.8-3.1-10.2 8.5-11.5 23.6-3.1 33.8 30 36 74.1 56.6 120.9 56.6s90.9-20.6 120.9-56.6c8.5-10.2 7.1-25.3-3.1-33.8-10.1-8.4-25.3-7.1-33.8 3.1z"] }, { prefix: "fas", iconName: "times", icon: [352, 512, [], "f00d", "M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z"] }, { prefix: "fas", iconName: "user", icon: [448, 512, [], "f007", "M224 256c70.7 0 128-57.3 128-128S294.7 0 224 0 96 57.3 96 128s57.3 128 128 128zm89.6 32h-16.7c-22.2 10.2-46.9 16-72.9 16s-50.6-5.8-72.9-16h-16.7C60.2 288 0 348.2 0 422.4V464c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48v-41.6c0-74.2-60.2-134.4-134.4-134.4z"] }); const Oo = zo({ prefix: "far", iconName: "building" }).html[0], Io = zo({ prefix: "fas", iconName: "cat" }).html[0], So = zo({ prefix: "fas", iconName: "coffee" }).html[0], Po = zo({ prefix: "far", iconName: "flag" }).html[0], Mo = zo({ prefix: "fas", iconName: "futbol" }).html[0], Ao = zo({ prefix: "far", iconName: "frown" }).html[0], Lo = zo({ prefix: "fas", iconName: "history" }).html[0], To = zo({ prefix: "fas", iconName: "icons" }).html[0], No = zo({ prefix: "far", iconName: "lightbulb" }).html[0], Fo = zo({ prefix: "fas", iconName: "music" }).html[0], Bo = zo({ prefix: "fas", iconName: "search" }).html[0], Do = zo({ prefix: "far", iconName: "smile" }).html[0], Ro = zo({ prefix: "fas", iconName: "times" }).html[0], qo = zo({ prefix: "fas", iconName: "user" }).html[0]; function Vo(e) { const o = document.createElement("img"); return o.src = e, o } function Ho() { const e = localStorage.getItem("emojiPicker.recent"); return (e ? JSON.parse(e) : []).filter((e => !!e.emoji)) } class Uo { constructor(e, o, n, i, a, r = !0) { this.emoji = e, this.showVariants = o, this.showPreview = n, this.events = i, this.options = a, this.lazy = r } render() { this.emojiButton = Ee("button", Ce); let e = this.emoji.emoji; return this.emoji.custom ? e = this.lazy ? Do : `<img class="emoji-picker__custom-emoji" src="${this.emoji.emoji}">` : "twemoji" === this.options.style && (e = this.lazy ? Do : ke.parse(this.emoji.emoji, this.options.twemojiOptions)), this.emojiButton.innerHTML = e, this.emojiButton.tabIndex = -1, this.emojiButton.dataset.emoji = this.emoji.emoji, this.emoji.custom && (this.emojiButton.dataset.custom = "true"), this.emojiButton.title = this.emoji.name, this.emojiButton.addEventListener("focus", (() => this.onEmojiHover())), this.emojiButton.addEventListener("blur", (() => this.onEmojiLeave())), this.emojiButton.addEventListener("click", (() => this.onEmojiClick())), this.emojiButton.addEventListener("mouseover", (() => this.onEmojiHover())), this.emojiButton.addEventListener("mouseout", (() => this.onEmojiLeave())), "twemoji" === this.options.style && this.lazy && (this.emojiButton.style.opacity = "0.25"), this.emojiButton } onEmojiClick() { this.emoji.variations && this.showVariants && this.options.showVariants || !this.options.showRecents || function (e, o) { const n = Ho(), i = { emoji: e.emoji, name: e.name, key: e.key || e.name, custom: e.custom }; localStorage.setItem("emojiPicker.recent", JSON.stringify([i, ...n.filter((e => !!e.emoji && e.key !== i.key))].slice(0, o.recentsCount))) }(this.emoji, this.options), this.events.emit("emoji", { emoji: this.emoji, showVariants: this.showVariants, button: this.emojiButton }) } onEmojiHover() { this.showPreview && this.events.emit("showPreview", this.emoji) } onEmojiLeave() { this.showPreview && this.events.emit("hidePreview") } } class Wo { constructor(e, o, n, i, a = !0) { this.showVariants = o, this.events = n, this.options = i, this.lazy = a, this.emojis = e.filter((e => !e.version || parseFloat(e.version) <= parseFloat(i.emojiVersion))) } render() { const e = Ee("div", "emoji-picker__container"); return this.emojis.forEach((o => e.appendChild(new Uo(o, this.showVariants, !0, this.events, this.options, this.lazy).render()))), e } } var Ko = "undefined" != typeof globalThis ? globalThis : "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof self ? self : {}; var Jo, Go = (function (e) { var o, n; o = Ko, n = function () { var e = "undefined" == typeof window, o = new Map, n = new Map, i = []; i.total = 0; var a = [], r = []; function t() { o.clear(), n.clear(), a = [], r = [] } function s(e) { for (var o = -9007199254740991, n = e.length - 1; n >= 0; --n) { var i = e[n]; if (null !== i) { var a = i.score; a > o && (o = a) } } return -9007199254740991 === o ? null : o } function m(e, o) { var n = e[o]; if (void 0 !== n) return n; var i = o; Array.isArray(o) || (i = o.split(".")); for (var a = i.length, r = -1; e && ++r < a;)e = e[i[r]]; return e } function c(e) { return "object" == typeof e } var d = function () { var e = [], o = 0, n = {}; function i() { for (var n = 0, i = e[n], a = 1; a < o;) { var r = a + 1; n = a, r < o && e[r].score < e[a].score && (n = r), e[n - 1 >> 1] = e[n], a = 1 + (n << 1) } for (var t = n - 1 >> 1; n > 0 && i.score < e[t].score; t = (n = t) - 1 >> 1)e[n] = e[t]; e[n] = i } return n.add = function (n) { var i = o; e[o++] = n; for (var a = i - 1 >> 1; i > 0 && n.score < e[a].score; a = (i = a) - 1 >> 1)e[i] = e[a]; e[i] = n }, n.poll = function () { if (0 !== o) { var n = e[0]; return e[0] = e[--o], i(), n } }, n.peek = function (n) { if (0 !== o) return e[0] }, n.replaceTop = function (o) { e[0] = o, i() }, n }, g = d(); return function u(l) { var v = { single: function (e, o, n) { return e ? (c(e) || (e = v.getPreparedSearch(e)), o ? (c(o) || (o = v.getPrepared(o)), ((n && void 0 !== n.allowTypo ? n.allowTypo : !l || void 0 === l.allowTypo || l.allowTypo) ? v.algorithm : v.algorithmNoTypo)(e, o, e[0])) : null) : null }, go: function (e, o, n) { if (!e) return i; var a = (e = v.prepareSearch(e))[0], r = n && n.threshold || l && l.threshold || -9007199254740991, t = n && n.limit || l && l.limit || 9007199254740991, d = (n && void 0 !== n.allowTypo ? n.allowTypo : !l || void 0 === l.allowTypo || l.allowTypo) ? v.algorithm : v.algorithmNoTypo, u = 0, f = 0, y = o.length; if (n && n.keys) for (var j = n.scoreFn || s, h = n.keys, p = h.length, b = y - 1; b >= 0; --b) { for (var w = o[b], k = new Array(p), x = p - 1; x >= 0; --x)(_ = m(w, E = h[x])) ? (c(_) || (_ = v.getPrepared(_)), k[x] = d(e, _, a)) : k[x] = null; k.obj = w; var C = j(k); null !== C && (C < r || (k.score = C, u < t ? (g.add(k), ++u) : (++f, C > g.peek().score && g.replaceTop(k)))) } else if (n && n.key) { var E = n.key; for (b = y - 1; b >= 0; --b)(_ = m(w = o[b], E)) && (c(_) || (_ = v.getPrepared(_)), null !== (z = d(e, _, a)) && (z.score < r || (z = { target: z.target, _targetLowerCodes: null, _nextBeginningIndexes: null, score: z.score, indexes: z.indexes, obj: w }, u < t ? (g.add(z), ++u) : (++f, z.score > g.peek().score && g.replaceTop(z))))) } else for (b = y - 1; b >= 0; --b) { var _, z; (_ = o[b]) && (c(_) || (_ = v.getPrepared(_)), null !== (z = d(e, _, a)) && (z.score < r || (u < t ? (g.add(z), ++u) : (++f, z.score > g.peek().score && g.replaceTop(z))))) } if (0 === u) return i; var O = new Array(u); for (b = u - 1; b >= 0; --b)O[b] = g.poll(); return O.total = u + f, O }, goAsync: function (o, n, a) { var r = !1, t = new Promise((function (t, g) { if (!o) return t(i); var u = (o = v.prepareSearch(o))[0], f = d(), y = n.length - 1, j = a && a.threshold || l && l.threshold || -9007199254740991, h = a && a.limit || l && l.limit || 9007199254740991, p = (a && void 0 !== a.allowTypo ? a.allowTypo : !l || void 0 === l.allowTypo || l.allowTypo) ? v.algorithm : v.algorithmNoTypo, b = 0, w = 0; function k() { if (r) return g("canceled"); var d = Date.now(); if (a && a.keys) for (var l = a.scoreFn || s, x = a.keys, C = x.length; y >= 0; --y) { for (var E = n[y], _ = new Array(C), z = C - 1; z >= 0; --z)(S = m(E, I = x[z])) ? (c(S) || (S = v.getPrepared(S)), _[z] = p(o, S, u)) : _[z] = null; _.obj = E; var O = l(_); if (null !== O && !(O < j) && (_.score = O, b < h ? (f.add(_), ++b) : (++w, O > f.peek().score && f.replaceTop(_)), y % 1e3 == 0 && Date.now() - d >= 10)) return void (e ? setImmediate(k) : setTimeout(k)) } else if (a && a.key) { for (var I = a.key; y >= 0; --y)if ((S = m(E = n[y], I)) && (c(S) || (S = v.getPrepared(S)), null !== (P = p(o, S, u)) && !(P.score < j) && (P = { target: P.target, _targetLowerCodes: null, _nextBeginningIndexes: null, score: P.score, indexes: P.indexes, obj: E }, b < h ? (f.add(P), ++b) : (++w, P.score > f.peek().score && f.replaceTop(P)), y % 1e3 == 0 && Date.now() - d >= 10))) return void (e ? setImmediate(k) : setTimeout(k)) } else for (; y >= 0; --y) { var S, P; if ((S = n[y]) && (c(S) || (S = v.getPrepared(S)), null !== (P = p(o, S, u)) && !(P.score < j) && (b < h ? (f.add(P), ++b) : (++w, P.score > f.peek().score && f.replaceTop(P)), y % 1e3 == 0 && Date.now() - d >= 10))) return void (e ? setImmediate(k) : setTimeout(k)) } if (0 === b) return t(i); for (var M = new Array(b), A = b - 1; A >= 0; --A)M[A] = f.poll(); M.total = b + w, t(M) } e ? setImmediate(k) : k() })); return t.cancel = function () { r = !0 }, t }, highlight: function (e, o, n) { if (null === e) return null; void 0 === o && (o = "<b>"), void 0 === n && (n = "</b>"); for (var i = "", a = 0, r = !1, t = e.target, s = t.length, m = e.indexes, c = 0; c < s; ++c) { var d = t[c]; if (m[a] === c) { if (r || (r = !0, i += o), ++a === m.length) { i += d + n + t.substr(c + 1); break } } else r && (r = !1, i += n); i += d } return i }, prepare: function (e) { if (e) return { target: e, _targetLowerCodes: v.prepareLowerCodes(e), _nextBeginningIndexes: null, score: null, indexes: null, obj: null } }, prepareSlow: function (e) { if (e) return { target: e, _targetLowerCodes: v.prepareLowerCodes(e), _nextBeginningIndexes: v.prepareNextBeginningIndexes(e), score: null, indexes: null, obj: null } }, prepareSearch: function (e) { if (e) return v.prepareLowerCodes(e) }, getPrepared: function (e) { if (e.length > 999) return v.prepare(e); var n = o.get(e); return void 0 !== n || (n = v.prepare(e), o.set(e, n)), n }, getPreparedSearch: function (e) { if (e.length > 999) return v.prepareSearch(e); var o = n.get(e); return void 0 !== o || (o = v.prepareSearch(e), n.set(e, o)), o }, algorithm: function (e, o, n) { for (var i = o._targetLowerCodes, t = e.length, s = i.length, m = 0, c = 0, d = 0, g = 0; ;) { if (n === i[c]) { if (a[g++] = c, ++m === t) break; n = e[0 === d ? m : d === m ? m + 1 : d === m - 1 ? m - 1 : m] } if (++c >= s) for (; ;) { if (m <= 1) return null; if (0 === d) { if (n === e[--m]) continue; d = m } else { if (1 === d) return null; if ((n = e[1 + (m = --d)]) === e[m]) continue } c = a[(g = m) - 1] + 1; break } } m = 0; var u = 0, l = !1, f = 0, y = o._nextBeginningIndexes; null === y && (y = o._nextBeginningIndexes = v.prepareNextBeginningIndexes(o.target)); var j = c = 0 === a[0] ? 0 : y[a[0] - 1]; if (c !== s) for (; ;)if (c >= s) { if (m <= 0) { if (++u > t - 2) break; if (e[u] === e[u + 1]) continue; c = j; continue } --m, c = y[r[--f]] } else if (e[0 === u ? m : u === m ? m + 1 : u === m - 1 ? m - 1 : m] === i[c]) { if (r[f++] = c, ++m === t) { l = !0; break } ++c } else c = y[c]; if (l) var h = r, p = f; else h = a, p = g; for (var b = 0, w = -1, k = 0; k < t; ++k)w !== (c = h[k]) - 1 && (b -= c), w = c; for (l ? 0 !== u && (b += -20) : (b *= 1e3, 0 !== d && (b += -20)), b -= s - t, o.score = b, o.indexes = new Array(p), k = p - 1; k >= 0; --k)o.indexes[k] = h[k]; return o }, algorithmNoTypo: function (e, o, n) { for (var i = o._targetLowerCodes, t = e.length, s = i.length, m = 0, c = 0, d = 0; ;) { if (n === i[c]) { if (a[d++] = c, ++m === t) break; n = e[m] } if (++c >= s) return null } m = 0; var g = !1, u = 0, l = o._nextBeginningIndexes; if (null === l && (l = o._nextBeginningIndexes = v.prepareNextBeginningIndexes(o.target)), (c = 0 === a[0] ? 0 : l[a[0] - 1]) !== s) for (; ;)if (c >= s) { if (m <= 0) break; --m, c = l[r[--u]] } else if (e[m] === i[c]) { if (r[u++] = c, ++m === t) { g = !0; break } ++c } else c = l[c]; if (g) var f = r, y = u; else f = a, y = d; for (var j = 0, h = -1, p = 0; p < t; ++p)h !== (c = f[p]) - 1 && (j -= c), h = c; for (g || (j *= 1e3), j -= s - t, o.score = j, o.indexes = new Array(y), p = y - 1; p >= 0; --p)o.indexes[p] = f[p]; return o }, prepareLowerCodes: function (e) { for (var o = e.length, n = [], i = e.toLowerCase(), a = 0; a < o; ++a)n[a] = i.charCodeAt(a); return n }, prepareBeginningIndexes: function (e) { for (var o = e.length, n = [], i = 0, a = !1, r = !1, t = 0; t < o; ++t) { var s = e.charCodeAt(t), m = s >= 65 && s <= 90, c = m || s >= 97 && s <= 122 || s >= 48 && s <= 57, d = m && !a || !r || !c; a = m, r = c, d && (n[i++] = t) } return n }, prepareNextBeginningIndexes: function (e) { for (var o = e.length, n = v.prepareBeginningIndexes(e), i = [], a = n[0], r = 0, t = 0; t < o; ++t)a > t ? i[t] = a : (a = n[++r], i[t] = void 0 === a ? o : a); return i }, cleanup: t, new: u }; return v }() }, e.exports ? e.exports = n() : o.fuzzysort = n() }(Jo = { exports: {} }, Jo.exports), Jo.exports); class Xo { constructor(e, o) { this.message = e, this.iconUrl = o } render() { const e = Ee("div", "emoji-picker__search-not-found"), o = Ee("div", "emoji-picker__search-not-found-icon"); this.iconUrl ? o.appendChild(Vo(this.iconUrl)) : o.innerHTML = Ao, e.appendChild(o); const n = Ee("h2"); return n.innerHTML = this.message, e.appendChild(n), e } } class Yo { constructor(e, o, n, i, a) { if (this.events = e, this.i18n = o, this.options = n, this.focusedEmojiIndex = 0, this.emojisPerRow = this.options.emojisPerRow || 8, this.emojiData = i.filter((e => e.version && parseFloat(e.version) <= parseFloat(n.emojiVersion) && void 0 !== e.category && a.indexOf(e.category) >= 0)), this.options.custom) { const e = this.options.custom.map((e => Object.assign(Object.assign({}, e), { custom: !0 }))); this.emojiData = [...this.emojiData, ...e] } this.events.on("hideVariantPopup", (() => { setTimeout((() => this.setFocusedEmoji(this.focusedEmojiIndex))) })) } render() { return this.searchContainer = Ee("div", "emoji-picker__search-container"), this.searchField = Ee("input", "emoji-picker__search"), this.searchField.placeholder = this.i18n.search, this.searchContainer.appendChild(this.searchField), this.searchIcon = Ee("span", "emoji-picker__search-icon"), this.options.icons && this.options.icons.search ? this.searchIcon.appendChild(Vo(this.options.icons.search)) : this.searchIcon.innerHTML = Bo, this.searchIcon.addEventListener("click", (e => this.onClearSearch(e))), this.searchContainer.appendChild(this.searchIcon), this.searchField.addEventListener("keydown", (e => this.onKeyDown(e))), this.searchField.addEventListener("keyup", (e => this.onKeyUp(e))), this.searchContainer } clear() { this.searchField.value = "" } focus() { this.searchField.focus() } onClearSearch(e) { e.stopPropagation(), this.searchField.value && (this.searchField.value = "", this.resultsContainer = null, this.options.icons && this.options.icons.search ? (_e(this.searchIcon), this.searchIcon.appendChild(Vo(this.options.icons.search))) : this.searchIcon.innerHTML = Bo, this.searchIcon.style.cursor = "default", this.events.emit("hideSearchResults"), setTimeout((() => this.searchField.focus()))) } setFocusedEmoji(e) { if (this.resultsContainer) { const o = this.resultsContainer.querySelectorAll("." + Ce); o[this.focusedEmojiIndex].tabIndex = -1, this.focusedEmojiIndex = e; const n = o[this.focusedEmojiIndex]; n.tabIndex = 0, n.focus() } } handleResultsKeydown(e) { if (this.resultsContainer) { const o = this.resultsContainer.querySelectorAll("." + Ce); "ArrowRight" === e.key ? this.setFocusedEmoji(Math.min(this.focusedEmojiIndex + 1, o.length - 1)) : "ArrowLeft" === e.key ? this.setFocusedEmoji(Math.max(0, this.focusedEmojiIndex - 1)) : "ArrowDown" === e.key ? (e.preventDefault(), this.focusedEmojiIndex < o.length - this.emojisPerRow && this.setFocusedEmoji(this.focusedEmojiIndex + this.emojisPerRow)) : "ArrowUp" === e.key ? (e.preventDefault(), this.focusedEmojiIndex >= this.emojisPerRow && this.setFocusedEmoji(this.focusedEmojiIndex - this.emojisPerRow)) : "Escape" === e.key && this.onClearSearch(e) } } onKeyDown(e) { "Escape" === e.key && this.searchField.value && this.onClearSearch(e) } onKeyUp(e) { if ("Tab" !== e.key && "Shift" !== e.key) if (this.searchField.value) { this.options.icons && this.options.icons.clearSearch ? (_e(this.searchIcon), this.searchIcon.appendChild(Vo(this.options.icons.clearSearch))) : this.searchIcon.innerHTML = Ro, this.searchIcon.style.cursor = "pointer"; const e = Go.go(this.searchField.value, this.emojiData, { allowTypo: !0, limit: 100, key: "name" }).map((e => e.obj)); this.events.emit("hidePreview"), e.length ? (this.resultsContainer = new Wo(e, !0, this.events, this.options, !1).render(), this.resultsContainer && (this.resultsContainer.querySelector("." + Ce).tabIndex = 0, this.focusedEmojiIndex = 0, this.resultsContainer.addEventListener("keydown", (e => this.handleResultsKeydown(e))), this.events.emit("showSearchResults", this.resultsContainer))) : this.events.emit("showSearchResults", new Xo(this.i18n.notFound, this.options.icons && this.options.icons.notFound).render()) } else this.options.icons && this.options.icons.search ? (_e(this.searchIcon), this.searchIcon.appendChild(Vo(this.options.icons.search))) : this.searchIcon.innerHTML = Bo, this.searchIcon.style.cursor = "default", this.events.emit("hideSearchResults") } } class $o { constructor(e, o, n) { this.events = e, this.emoji = o, this.options = n, this.focusedEmojiIndex = 0 } getEmoji(e) { return this.popup.querySelectorAll("." + Ce)[e] } setFocusedEmoji(e) { this.getEmoji(this.focusedEmojiIndex).tabIndex = -1, this.focusedEmojiIndex = e; const o = this.getEmoji(this.focusedEmojiIndex); o.tabIndex = 0, o.focus() } render() { this.popup = Ee("div", "emoji-picker__variant-popup"); const e = Ee("div", "emoji-picker__variant-overlay"); e.addEventListener("click", (e => { e.stopPropagation(), this.popup.contains(e.target) || this.events.emit("hideVariantPopup") })), this.popup.appendChild(new Uo(this.emoji, !1, !1, this.events, this.options, !1).render()), (this.emoji.variations || []).forEach(((e, o) => this.popup.appendChild(new Uo({ name: this.emoji.name, emoji: e, key: this.emoji.name + o }, !1, !1, this.events, this.options, !1).render()))); const o = this.popup.querySelector("." + Ce); return this.focusedEmojiIndex = 0, o.tabIndex = 0, setTimeout((() => o.focus())), this.popup.addEventListener("keydown", (e => { "ArrowRight" === e.key ? this.setFocusedEmoji(Math.min(this.focusedEmojiIndex + 1, this.popup.querySelectorAll("." + Ce).length - 1)) : "ArrowLeft" === e.key ? this.setFocusedEmoji(Math.max(this.focusedEmojiIndex - 1, 0)) : "Escape" === e.key && (e.stopPropagation(), this.events.emit("hideVariantPopup")) })), e.appendChild(this.popup), e } } const Zo = { search: "Search emojis...", categories: { recents: "Recent Emojis", smileys: "Smileys & Emotion", people: "People & Body", animals: "Animals & Nature", food: "Food & Drink", activities: "Activities", travel: "Travel & Places", objects: "Objects", symbols: "Symbols", flags: "Flags", custom: "Custom" }, notFound: "No emojis found" }, Qo = { recents: Lo, smileys: Do, people: qo, animals: Io, food: So, activities: Mo, travel: Oo, objects: No, symbols: Fo, flags: Po, custom: To }; class en { constructor(e, o, n) { this.options = e, this.events = o, this.i18n = n, this.activeButton = 0, this.buttons = [] } render() { var e; const o = Ee("div", "emoji-picker__category-buttons"), n = this.options.categories || (null === (e = this.options.emojiData) || void 0 === e ? void 0 : e.categories) || xe.categories; let i = this.options.showRecents ? ["recents", ...n] : n; return this.options.custom && (i = [...i, "custom"]), i.forEach((e => { const n = Ee("button", "emoji-picker__category-button"); this.options.icons && this.options.icons.categories && this.options.icons.categories[e] ? n.appendChild(Vo(this.options.icons.categories[e])) : n.innerHTML = Qo[e], n.tabIndex = -1, n.title = this.i18n.categories[e], o.appendChild(n), this.buttons.push(n), n.addEventListener("click", (() => { this.events.emit("categoryClicked", e) })) })), o.addEventListener("keydown", (e => { switch (e.key) { case "ArrowRight": this.events.emit("categoryClicked", i[(this.activeButton + 1) % this.buttons.length]); break; case "ArrowLeft": this.events.emit("categoryClicked", i[0 === this.activeButton ? this.buttons.length - 1 : this.activeButton - 1]); break; case "ArrowUp": case "ArrowDown": e.stopPropagation(), e.preventDefault() } })), o } setActiveButton(e, o = !0) { let n = this.buttons[this.activeButton]; n.classList.remove("active"), n.tabIndex = -1, this.activeButton = e, n = this.buttons[this.activeButton], n.classList.add("active"), n.tabIndex = 0, o && n.focus() } } const on = ["recents", "smileys", "people", "animals", "food", "activities", "travel", "objects", "symbols", "flags", "custom"]; class nn { constructor(e, o, n, i) { var a; this.events = e, this.i18n = o, this.options = n, this.emojiCategories = i, this.currentCategory = 0, this.headers = [], this.focusedIndex = 0, this.handleKeyDown = e => { switch (this.emojis.removeEventListener("scroll", this.highlightCategory), e.key) { case "ArrowRight": this.focusedEmoji.tabIndex = -1, this.focusedIndex === this.currentEmojiCount - 1 && this.currentCategory < this.categories.length - 1 ? (this.options.showCategoryButtons && this.categoryButtons.setActiveButton(++this.currentCategory), this.setFocusedEmoji(0)) : this.focusedIndex < this.currentEmojiCount - 1 && this.setFocusedEmoji(this.focusedIndex + 1); break; case "ArrowLeft": this.focusedEmoji.tabIndex = -1, 0 === this.focusedIndex && this.currentCategory > 0 ? (this.options.showCategoryButtons && this.categoryButtons.setActiveButton(--this.currentCategory), this.setFocusedEmoji(this.currentEmojiCount - 1)) : this.setFocusedEmoji(Math.max(0, this.focusedIndex - 1)); break; case "ArrowDown": e.preventDefault(), this.focusedEmoji.tabIndex = -1, this.focusedIndex + this.emojisPerRow >= this.currentEmojiCount && this.currentCategory < this.categories.length - 1 ? (this.currentCategory++ , this.options.showCategoryButtons && this.categoryButtons.setActiveButton(this.currentCategory), this.setFocusedEmoji(Math.min(this.focusedIndex % this.emojisPerRow, this.currentEmojiCount - 1))) : this.currentEmojiCount - this.focusedIndex > this.emojisPerRow && this.setFocusedEmoji(this.focusedIndex + this.emojisPerRow); break; case "ArrowUp": if (e.preventDefault(), this.focusedEmoji.tabIndex = -1, this.focusedIndex < this.emojisPerRow && this.currentCategory > 0) { const e = this.getEmojiCount(this.currentCategory - 1); let o = e % this.emojisPerRow; 0 === o && (o = this.emojisPerRow); const n = this.focusedIndex, i = n > o - 1 ? e - 1 : e - o + n; this.currentCategory-- , this.options.showCategoryButtons && this.categoryButtons.setActiveButton(this.currentCategory), this.setFocusedEmoji(i) } else this.setFocusedEmoji(this.focusedIndex >= this.emojisPerRow ? this.focusedIndex - this.emojisPerRow : this.focusedIndex) }requestAnimationFrame((() => this.emojis.addEventListener("scroll", this.highlightCategory))) }, this.addCategory = (e, o) => { const n = Ee("h2", "emoji-picker__category-name"); n.innerHTML = this.i18n.categories[e] || Zo.categories[e], this.emojis.appendChild(n), this.headers.push(n), this.emojis.appendChild(new Wo(o, !0, this.events, this.options, "recents" !== e).render()) }, this.selectCategory = (e, o = !0) => { this.emojis.removeEventListener("scroll", this.highlightCategory), this.focusedEmoji && (this.focusedEmoji.tabIndex = -1); const n = this.categories.indexOf(e); this.currentCategory = n, this.setFocusedEmoji(0, !1), this.options.showCategoryButtons && this.categoryButtons.setActiveButton(this.currentCategory, o); const i = this.headerOffsets[n]; this.emojis.scrollTop = i, requestAnimationFrame((() => this.emojis.addEventListener("scroll", this.highlightCategory))) }, this.highlightCategory = () => { if (document.activeElement && document.activeElement.classList.contains("emoji-picker__emoji")) return; let e = this.headerOffsets.findIndex((e => e >= Math.round(this.emojis.scrollTop))); this.emojis.scrollTop + this.emojis.offsetHeight === this.emojis.scrollHeight && (e = -1), 0 === e ? e = 1 : e < 0 && (e = this.headerOffsets.length), this.headerOffsets[e] === this.emojis.scrollTop && e++ , this.currentCategory = e - 1, this.options.showCategoryButtons && this.categoryButtons.setActiveButton(this.currentCategory) }, this.emojisPerRow = n.emojisPerRow || 8, this.categories = (null === (a = n.emojiData) || void 0 === a ? void 0 : a.categories) || n.categories || xe.categories, n.showRecents && (this.categories = ["recents", ...this.categories]), n.custom && (this.categories = [...this.categories, "custom"]), this.categories.sort(((e, o) => on.indexOf(e) - on.indexOf(o))) } updateRecents() { if (this.options.showRecents) { this.emojiCategories.recents = Ho(); const e = this.emojis.querySelector(".emoji-picker__container"); e && e.parentNode && e.parentNode.replaceChild(new Wo(this.emojiCategories.recents, !0, this.events, this.options, !1).render(), e) } } render() { this.container = Ee("div", "emoji-picker__emoji-area"), this.options.showCategoryButtons && (this.categoryButtons = new en(this.options, this.events, this.i18n), this.container.appendChild(this.categoryButtons.render())), this.emojis = Ee("div", "emoji-picker__emojis"), this.options.showRecents && (this.emojiCategories.recents = Ho()), this.options.custom && (this.emojiCategories.custom = this.options.custom.map((e => Object.assign(Object.assign({}, e), { custom: !0 })))), this.categories.forEach((e => this.addCategory(e, this.emojiCategories[e]))), requestAnimationFrame((() => { setTimeout((() => { setTimeout((() => this.emojis.addEventListener("scroll", this.highlightCategory))) })) })), this.emojis.addEventListener("keydown", this.handleKeyDown), this.events.on("categoryClicked", this.selectCategory), this.container.appendChild(this.emojis); return this.container.querySelectorAll("." + Ce)[0].tabIndex = 0, this.container } reset() { this.headerOffsets = Array.prototype.map.call(this.headers, (e => e.offsetTop)), this.selectCategory(this.options.initialCategory || "smileys", !1), this.currentCategory = this.categories.indexOf(this.options.initialCategory || "smileys"), this.options.showCategoryButtons && this.categoryButtons.setActiveButton(this.currentCategory, !1) } get currentCategoryEl() { return this.emojis.querySelectorAll(".emoji-picker__container")[this.currentCategory] } get focusedEmoji() { return this.currentCategoryEl.querySelectorAll("." + Ce)[this.focusedIndex] } get currentEmojiCount() { return this.currentCategoryEl.querySelectorAll("." + Ce).length } getEmojiCount(e) { return this.emojis.querySelectorAll(".emoji-picker__container")[e].querySelectorAll("." + Ce).length } setFocusedEmoji(e, o = !0) { this.focusedIndex = e, this.focusedEmoji && (this.focusedEmoji.tabIndex = 0, o && this.focusedEmoji.focus()) } } const an = { position: "auto", autoHide: !0, autoFocusSearch: !0, showAnimation: !0, showPreview: !0, showSearch: !0, showRecents: !0, showVariants: !0, showCategoryButtons: !0, recentsCount: 50, emojiData: xe, emojiVersion: "12.1", theme: "light", categories: ["smileys", "people", "animals", "food", "activities", "travel", "objects", "symbols", "flags"], style: "native", twemojiOptions: { ext: ".svg", folder: "svg" }, emojisPerRow: 8, rows: 6, emojiSize: "1.8em", initialCategory: "smileys" }; class EmojiButton { constructor(e = {}) { this.events = new b, this.publicEvents = new b, this.pickerVisible = !1, this.options = Object.assign(Object.assign({}, an), e), this.options.rootElement || (this.options.rootElement = document.body), this.i18n = Object.assign(Object.assign({}, Zo), e.i18n), this.onDocumentClick = this.onDocumentClick.bind(this), this.onDocumentKeydown = this.onDocumentKeydown.bind(this), this.theme = this.options.theme || "light", this.emojiCategories = function (e) { const o = {}; return e.emoji.forEach((n => { let i = o[e.categories[n.category || 0]]; i || (i = o[e.categories[n.category || 0]] = []), i.push(n) })), o }(this.options.emojiData || xe), this.buildPicker() } on(e, o) { this.publicEvents.on(e, o) } off(e, o) { this.publicEvents.off(e, o) } setStyleProperties() { this.options.showAnimation || this.pickerEl.style.setProperty("--animation-duration", "0s"), this.options.emojisPerRow && this.pickerEl.style.setProperty("--emoji-per-row", this.options.emojisPerRow.toString()), this.options.rows && this.pickerEl.style.setProperty("--row-count", this.options.rows.toString()), this.options.emojiSize && this.pickerEl.style.setProperty("--emoji-size", this.options.emojiSize), this.options.showCategoryButtons || this.pickerEl.style.setProperty("--category-button-height", "0"), this.options.styleProperties && Object.keys(this.options.styleProperties).forEach((e => { this.options.styleProperties && this.pickerEl.style.setProperty(e, this.options.styleProperties[e]) })) } showSearchResults(e) { _e(this.pickerContent), e.classList.add("search-results"), this.pickerContent.appendChild(e) } hideSearchResults() { this.pickerContent.firstChild !== this.emojiArea.container && (_e(this.pickerContent), this.pickerContent.appendChild(this.emojiArea.container)), this.emojiArea.reset() } emitEmoji({ emoji: o, showVariants: n }) { return e(this, void 0, void 0, (function* () { if (o.variations && n && this.options.showVariants) this.showVariantPopup(o); else { let e; setTimeout((() => this.emojiArea.updateRecents())), e = o.custom ? this.emitCustomEmoji(o) : "twemoji" === this.options.style ? yield this.emitTwemoji(o) : this.emitNativeEmoji(o), this.publicEvents.emit("emoji", e), this.options.autoHide && this.hidePicker() } })) } emitNativeEmoji(e) { return { emoji: e.emoji, name: e.name } } emitCustomEmoji(e) { return { url: e.emoji, name: e.name, custom: !0 } } emitTwemoji(e) { return new Promise((o => { ke.parse(e.emoji, Object.assign(Object.assign({}, this.options.twemojiOptions), { callback: (n, { base: i, size: a, ext: r }) => { const t = `${i}${a}/${n}${r}`; return o({ url: t, emoji: e.emoji, name: e.name }), t } })) })) } buildSearch() { var e; this.options.showSearch && (this.search = new Yo(this.events, this.i18n, this.options, (null === (e = this.options.emojiData) || void 0 === e ? void 0 : e.emoji) || xe.emoji, (this.options.categories || []).map((e => (this.options.emojiData || xe).categories.indexOf(e)))), this.pickerEl.appendChild(this.search.render())) } buildPreview() { this.options.showPreview && this.pickerEl.appendChild(new Oe(this.events, this.options).render()) } initPlugins() { if (this.options.plugins) { const e = Ee("div", "emoji-picker__plugin-container"); this.options.plugins.forEach((o => { if (!o.render) throw new Error('Emoji Button plugins must have a "render" function.'); e.appendChild(o.render(this)) })), this.pickerEl.appendChild(e) } } initFocusTrap() { this.focusTrap = h(this.pickerEl, { clickOutsideDeactivates: !0, initialFocus: this.options.showSearch && this.options.autoFocusSearch ? ".emoji-picker__search" : '.emoji-picker__emoji[tabindex="0"]' }) } buildPicker() { this.pickerEl = Ee("div", "emoji-picker"), this.pickerEl.classList.add(this.theme), this.setStyleProperties(), this.initFocusTrap(), this.pickerContent = Ee("div", "emoji-picker__content"), this.initPlugins(), this.buildSearch(), this.pickerEl.appendChild(this.pickerContent), this.emojiArea = new nn(this.events, this.i18n, this.options, this.emojiCategories), this.pickerContent.appendChild(this.emojiArea.render()), this.events.on("showSearchResults", this.showSearchResults.bind(this)), this.events.on("hideSearchResults", this.hideSearchResults.bind(this)), this.events.on("emoji", this.emitEmoji.bind(this)), this.buildPreview(), this.wrapper = Ee("div", "emoji-picker__wrapper"), this.wrapper.appendChild(this.pickerEl), this.wrapper.style.display = "none", this.options.zIndex && (this.wrapper.style.zIndex = this.options.zIndex + ""), this.options.rootElement && this.options.rootElement.appendChild(this.wrapper), this.observeForLazyLoad() } showVariantPopup(e) { const o = new $o(this.events, e, this.options).render(); o && this.pickerEl.appendChild(o), this.events.on("hideVariantPopup", (() => { o && (o.classList.add("hiding"), setTimeout((() => { o && this.pickerEl.removeChild(o) }), 175)), this.events.off("hideVariantPopup") })) } observeForLazyLoad() { this.observer = new IntersectionObserver(this.handleIntersectionChange.bind(this), { root: this.emojiArea.emojis }), this.emojiArea.emojis.querySelectorAll("." + Ce).forEach((e => { this.shouldLazyLoad(e) && this.observer.observe(e) })) } handleIntersectionChange(e) { Array.prototype.filter.call(e, (e => e.intersectionRatio > 0)).map((e => e.target)).forEach((e => { ze(e, this.options) })) } shouldLazyLoad(e) { return "twemoji" === this.options.style || "true" === e.dataset.custom } onDocumentClick(e) { this.pickerEl.contains(e.target) || this.hidePicker() } destroyPicker() { this.events.off("emoji"), this.events.off("hideVariantPopup"), this.options.rootElement && (this.options.rootElement.removeChild(this.wrapper), this.popper && this.popper.destroy()), this.observer && this.observer.disconnect(), this.options.plugins && this.options.plugins.forEach((e => { e.destroy && e.destroy() })) } hidePicker() { this.hideInProgress = !0, this.focusTrap.deactivate(), this.pickerVisible = !1, this.overlay && (document.body.removeChild(this.overlay), this.overlay = void 0), this.emojiArea.emojis.removeEventListener("scroll", this.emojiArea.highlightCategory), this.pickerEl.classList.add("hiding"), setTimeout((() => { this.wrapper.style.display = "none", this.pickerEl.classList.remove("hiding"), this.pickerContent.firstChild !== this.emojiArea.container && (_e(this.pickerContent), this.pickerContent.appendChild(this.emojiArea.container)), this.search && this.search.clear(), this.events.emit("hideVariantPopup"), this.hideInProgress = !1, this.popper && this.popper.destroy(), this.publicEvents.emit("hidden") }), this.options.showAnimation ? 170 : 0), setTimeout((() => { document.removeEventListener("click", this.onDocumentClick), document.removeEventListener("keydown", this.onDocumentKeydown) })) } showPicker(e) { this.hideInProgress ? setTimeout((() => this.showPicker(e)), 100) : (this.pickerVisible = !0, this.wrapper.style.display = "block", this.determineDisplay(e), this.focusTrap.activate(), setTimeout((() => { this.addEventListeners(), this.setInitialFocus() })), this.emojiArea.reset()) } determineDisplay(e) { window.matchMedia("screen and (max-width: 450px)").matches ? this.showMobileView() : "string" == typeof this.options.position ? this.setRelativePosition(e) : this.setFixedPosition() } setInitialFocus() { this.pickerEl.querySelector(this.options.showSearch && this.options.autoFocusSearch ? ".emoji-picker__search" : `.${Ce}[tabindex="0"]`).focus() } addEventListeners() { document.addEventListener("click", this.onDocumentClick), document.addEventListener("keydown", this.onDocumentKeydown) } setRelativePosition(e) { this.popper = we(e, this.wrapper, { placement: this.options.position }) } setFixedPosition() { var e; if (null === (e = this.options) || void 0 === e ? void 0 : e.position) { this.wrapper.style.position = "fixed"; const e = this.options.position; Object.keys(e).forEach((o => { this.wrapper.style[o] = e[o] })) } } showMobileView() { const e = window.getComputedStyle(this.pickerEl), o = document.querySelector("html"), n = o && o.clientHeight, i = o && o.clientWidth, a = parseInt(e.height), r = n ? n / 2 - a / 2 : 0, t = parseInt(e.width), s = i ? i / 2 - t / 2 : 0; this.wrapper.style.position = "fixed", this.wrapper.style.top = r + "px", this.wrapper.style.left = s + "px", this.wrapper.style.zIndex = "5000", this.overlay = Ee("div", "emoji-picker__overlay"), document.body.appendChild(this.overlay) } togglePicker(e) { this.pickerVisible ? this.hidePicker() : this.showPicker(e) } isPickerVisible() { return this.pickerVisible } onDocumentKeydown(e) { "Escape" === e.key ? this.hidePicker() : "Tab" === e.key ? this.pickerEl.classList.add("keyboard") : e.key.match(/^[\w]$/) && this.search && this.search.focus() } setTheme(e) { e !== this.theme && (this.pickerEl.classList.remove(this.theme), this.theme = e, this.pickerEl.classList.add(e)) } } diff --git a/src/libclient/web-chatview/fa.css b/src/libclient/web-chatview/fa.css new file mode 100644 index 0000000000000000000000000000000000000000..251acf7b9d090cea872cfe543acda157841aed14 --- /dev/null +++ b/src/libclient/web-chatview/fa.css @@ -0,0 +1,452 @@ +svg:not(:root).svg-inline--fa { + overflow: visible; +} + +.svg-inline--fa { + display: inline-block; + font-size: inherit; + height: 1em; + overflow: visible; + vertical-align: -0.125em; +} +.svg-inline--fa.fa-lg { + vertical-align: -0.225em; +} +.svg-inline--fa.fa-w-1 { + width: 0.0625em; +} +.svg-inline--fa.fa-w-2 { + width: 0.125em; +} +.svg-inline--fa.fa-w-3 { + width: 0.1875em; +} +.svg-inline--fa.fa-w-4 { + width: 0.25em; +} +.svg-inline--fa.fa-w-5 { + width: 0.3125em; +} +.svg-inline--fa.fa-w-6 { + width: 0.375em; +} +.svg-inline--fa.fa-w-7 { + width: 0.4375em; +} +.svg-inline--fa.fa-w-8 { + width: 0.5em; +} +.svg-inline--fa.fa-w-9 { + width: 0.5625em; +} +.svg-inline--fa.fa-w-10 { + width: 0.625em; +} +.svg-inline--fa.fa-w-11 { + width: 0.6875em; +} +.svg-inline--fa.fa-w-12 { + width: 0.75em; +} +.svg-inline--fa.fa-w-13 { + width: 0.8125em; +} +.svg-inline--fa.fa-w-14 { + width: 0.875em; +} +.svg-inline--fa.fa-w-15 { + width: 0.9375em; +} +.svg-inline--fa.fa-w-16 { + width: 1em; +} +.svg-inline--fa.fa-w-17 { + width: 1.0625em; +} +.svg-inline--fa.fa-w-18 { + width: 1.125em; +} +.svg-inline--fa.fa-w-19 { + width: 1.1875em; +} +.svg-inline--fa.fa-w-20 { + width: 1.25em; +} +.svg-inline--fa.fa-pull-left { + margin-right: 0.3em; + width: auto; +} +.svg-inline--fa.fa-pull-right { + margin-left: 0.3em; + width: auto; +} +.svg-inline--fa.fa-border { + height: 1.5em; +} +.svg-inline--fa.fa-li { + width: 2em; +} +.svg-inline--fa.fa-fw { + width: 1.25em; +} + +.fa-layers svg.svg-inline--fa { + bottom: 0; + left: 0; + margin: auto; + position: absolute; + right: 0; + top: 0; +} + +.fa-layers { + display: inline-block; + height: 1em; + position: relative; + text-align: center; + vertical-align: -0.125em; + width: 1em; +} +.fa-layers svg.svg-inline--fa { + -webkit-transform-origin: center center; + transform-origin: center center; +} + +.fa-layers-counter, .fa-layers-text { + display: inline-block; + position: absolute; + text-align: center; +} + +.fa-layers-text { + left: 50%; + top: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + -webkit-transform-origin: center center; + transform-origin: center center; +} + +.fa-layers-counter { + background-color: #ff253a; + border-radius: 1em; + -webkit-box-sizing: border-box; + box-sizing: border-box; + color: #fff; + height: 1.5em; + line-height: 1; + max-width: 5em; + min-width: 1.5em; + overflow: hidden; + padding: 0.25em; + right: 0; + text-overflow: ellipsis; + top: 0; + -webkit-transform: scale(0.25); + transform: scale(0.25); + -webkit-transform-origin: top right; + transform-origin: top right; +} + +.fa-layers-bottom-right { + bottom: 0; + right: 0; + top: auto; + -webkit-transform: scale(0.25); + transform: scale(0.25); + -webkit-transform-origin: bottom right; + transform-origin: bottom right; +} + +.fa-layers-bottom-left { + bottom: 0; + left: 0; + right: auto; + top: auto; + -webkit-transform: scale(0.25); + transform: scale(0.25); + -webkit-transform-origin: bottom left; + transform-origin: bottom left; +} + +.fa-layers-top-right { + right: 0; + top: 0; + -webkit-transform: scale(0.25); + transform: scale(0.25); + -webkit-transform-origin: top right; + transform-origin: top right; +} + +.fa-layers-top-left { + left: 0; + right: auto; + top: 0; + -webkit-transform: scale(0.25); + transform: scale(0.25); + -webkit-transform-origin: top left; + transform-origin: top left; +} + +.fa-lg { + font-size: 1.3333333333em; + line-height: 0.75em; + vertical-align: -0.0667em; +} + +.fa-xs { + font-size: 0.75em; +} + +.fa-sm { + font-size: 0.875em; +} + +.fa-1x { + font-size: 1em; +} + +.fa-2x { + font-size: 2em; +} + +.fa-3x { + font-size: 3em; +} + +.fa-4x { + font-size: 4em; +} + +.fa-5x { + font-size: 5em; +} + +.fa-6x { + font-size: 6em; +} + +.fa-7x { + font-size: 7em; +} + +.fa-8x { + font-size: 8em; +} + +.fa-9x { + font-size: 9em; +} + +.fa-10x { + font-size: 10em; +} + +.fa-fw { + text-align: center; + width: 1.25em; +} + +.fa-ul { + list-style-type: none; + margin-left: 2.5em; + padding-left: 0; +} +.fa-ul > li { + position: relative; +} + +.fa-li { + left: -2em; + position: absolute; + text-align: center; + width: 2em; + line-height: inherit; +} + +.fa-border { + border: solid 0.08em #eee; + border-radius: 0.1em; + padding: 0.2em 0.25em 0.15em; +} + +.fa-pull-left { + float: left; +} + +.fa-pull-right { + float: right; +} + +.fa.fa-pull-left, +.fas.fa-pull-left, +.far.fa-pull-left, +.fal.fa-pull-left, +.fab.fa-pull-left { + margin-right: 0.3em; +} +.fa.fa-pull-right, +.fas.fa-pull-right, +.far.fa-pull-right, +.fal.fa-pull-right, +.fab.fa-pull-right { + margin-left: 0.3em; +} + +.fa-spin { + -webkit-animation: fa-spin 2s infinite linear; + animation: fa-spin 2s infinite linear; +} + +.fa-pulse { + -webkit-animation: fa-spin 1s infinite steps(8); + animation: fa-spin 1s infinite steps(8); +} + +@-webkit-keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} + +@keyframes fa-spin { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(360deg); + transform: rotate(360deg); + } +} +.fa-rotate-90 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"; + -webkit-transform: rotate(90deg); + transform: rotate(90deg); +} + +.fa-rotate-180 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)"; + -webkit-transform: rotate(180deg); + transform: rotate(180deg); +} + +.fa-rotate-270 { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)"; + -webkit-transform: rotate(270deg); + transform: rotate(270deg); +} + +.fa-flip-horizontal { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)"; + -webkit-transform: scale(-1, 1); + transform: scale(-1, 1); +} + +.fa-flip-vertical { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; + -webkit-transform: scale(1, -1); + transform: scale(1, -1); +} + +.fa-flip-both, .fa-flip-horizontal.fa-flip-vertical { + -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)"; + -webkit-transform: scale(-1, -1); + transform: scale(-1, -1); +} + +:root .fa-rotate-90, +:root .fa-rotate-180, +:root .fa-rotate-270, +:root .fa-flip-horizontal, +:root .fa-flip-vertical, +:root .fa-flip-both { + -webkit-filter: none; + filter: none; +} + +.fa-stack { + display: inline-block; + height: 2em; + position: relative; + width: 2.5em; +} + +.fa-stack-1x, +.fa-stack-2x { + bottom: 0; + left: 0; + margin: auto; + position: absolute; + right: 0; + top: 0; +} + +.svg-inline--fa.fa-stack-1x { + height: 1em; + width: 1.25em; +} +.svg-inline--fa.fa-stack-2x { + height: 2em; + width: 2.5em; +} + +.fa-inverse { + color: #fff; +} + +.sr-only { + border: 0; + clip: rect(0, 0, 0, 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} + +.sr-only-focusable:active, .sr-only-focusable:focus { + clip: auto; + height: auto; + margin: 0; + overflow: visible; + position: static; + width: auto; +} + +.svg-inline--fa .fa-primary { + fill: var(--fa-primary-color, currentColor); + opacity: 1; + opacity: var(--fa-primary-opacity, 1); +} + +.svg-inline--fa .fa-secondary { + fill: var(--fa-secondary-color, currentColor); + opacity: 0.4; + opacity: var(--fa-secondary-opacity, 0.4); +} + +.svg-inline--fa.fa-swap-opacity .fa-primary { + opacity: 0.4; + opacity: var(--fa-secondary-opacity, 0.4); +} + +.svg-inline--fa.fa-swap-opacity .fa-secondary { + opacity: 1; + opacity: var(--fa-primary-opacity, 1); +} + +.svg-inline--fa mask .fa-primary, +.svg-inline--fa mask .fa-secondary { + fill: black; +} + +.fad.fa-inverse { + color: #fff; +} diff --git a/src/libclient/web-chatview/jed.js b/src/libclient/web-chatview/jed.js new file mode 100644 index 0000000000000000000000000000000000000000..bb306e99d438072ce3ca3dd9c2f84676420aaa73 --- /dev/null +++ b/src/libclient/web-chatview/jed.js @@ -0,0 +1,1033 @@ +/** + * @preserve jed.js https://github.com/SlexAxton/Jed + */ +/* +----------- +A gettext compatible i18n library for modern JavaScript Applications + +by Alex Sexton - AlexSexton [at] gmail - @SlexAxton + +MIT License + +A jQuery Foundation project - requires CLA to contribute - +https://contribute.jquery.org/CLA/ + + + +Jed offers the entire applicable GNU gettext spec'd set of +functions, but also offers some nicer wrappers around them. +The api for gettext was written for a language with no function +overloading, so Jed allows a little more of that. + +Many thanks to Joshua I. Miller - unrtst@cpan.org - who wrote +gettext.js back in 2008. I was able to vet a lot of my ideas +against his. I also made sure Jed passed against his tests +in order to offer easy upgrades -- jsgettext.berlios.de +*/ +(function (root, undef) { + + // Set up some underscore-style functions, if you already have + // underscore, feel free to delete this section, and use it + // directly, however, the amount of functions used doesn't + // warrant having underscore as a full dependency. + // Underscore 1.3.0 was used to port and is licensed + // under the MIT License by Jeremy Ashkenas. + var ArrayProto = Array.prototype, + ObjProto = Object.prototype, + slice = ArrayProto.slice, + hasOwnProp = ObjProto.hasOwnProperty, + nativeForEach = ArrayProto.forEach, + breaker = {}; + + // We're not using the OOP style _ so we don't need the + // extra level of indirection. This still means that you + // sub out for real `_` though. + var _ = { + forEach : function( obj, iterator, context ) { + var i, l, key; + if ( obj === null ) { + return; + } + + if ( nativeForEach && obj.forEach === nativeForEach ) { + obj.forEach( iterator, context ); + } + else if ( obj.length === +obj.length ) { + for ( i = 0, l = obj.length; i < l; i++ ) { + if ( i in obj && iterator.call( context, obj[i], i, obj ) === breaker ) { + return; + } + } + } + else { + for ( key in obj) { + if ( hasOwnProp.call( obj, key ) ) { + if ( iterator.call (context, obj[key], key, obj ) === breaker ) { + return; + } + } + } + } + }, + extend : function( obj ) { + this.forEach( slice.call( arguments, 1 ), function ( source ) { + for ( var prop in source ) { + obj[prop] = source[prop]; + } + }); + return obj; + } + }; + // END Miniature underscore impl + + // Jed is a constructor function + var Jed = function ( options ) { + // Some minimal defaults + this.defaults = { + "locale_data" : { + "messages" : { + "" : { + "domain" : "messages", + "lang" : "en", + "plural_forms" : "nplurals=2; plural=(n != 1);" + } + // There are no default keys, though + } + }, + // The default domain if one is missing + "domain" : "messages", + // enable debug mode to log untranslated strings to the console + "debug" : false + }; + + // Mix in the sent options with the default options + this.options = _.extend( {}, this.defaults, options ); + this.textdomain( this.options.domain ); + + if ( options.domain && ! this.options.locale_data[ this.options.domain ] ) { + throw new Error('Text domain set to non-existent domain: `' + options.domain + '`'); + } + }; + + // The gettext spec sets this character as the default + // delimiter for context lookups. + // e.g.: context\u0004key + // If your translation company uses something different, + // just change this at any time and it will use that instead. + Jed.context_delimiter = String.fromCharCode( 4 ); + + function getPluralFormFunc ( plural_form_string ) { + return Jed.PF.compile( plural_form_string || "nplurals=2; plural=(n != 1);"); + } + + function Chain( key, i18n ){ + this._key = key; + this._i18n = i18n; + } + + // Create a chainable api for adding args prettily + _.extend( Chain.prototype, { + onDomain : function ( domain ) { + this._domain = domain; + return this; + }, + withContext : function ( context ) { + this._context = context; + return this; + }, + ifPlural : function ( num, pkey ) { + this._val = num; + this._pkey = pkey; + return this; + }, + fetch : function ( sArr ) { + if ( {}.toString.call( sArr ) != '[object Array]' ) { + sArr = [].slice.call(arguments, 0); + } + return ( sArr && sArr.length ? Jed.sprintf : function(x){ return x; } )( + this._i18n.dcnpgettext(this._domain, this._context, this._key, this._pkey, this._val), + sArr + ); + } + }); + + // Add functions to the Jed prototype. + // These will be the functions on the object that's returned + // from creating a `new Jed()` + // These seem redundant, but they gzip pretty well. + _.extend( Jed.prototype, { + // The sexier api start point + translate : function ( key ) { + return new Chain( key, this ); + }, + + textdomain : function ( domain ) { + if ( ! domain ) { + return this._textdomain; + } + this._textdomain = domain; + }, + + gettext : function ( key ) { + return this.dcnpgettext.call( this, undef, undef, key ); + }, + + dgettext : function ( domain, key ) { + return this.dcnpgettext.call( this, domain, undef, key ); + }, + + dcgettext : function ( domain , key /*, category */ ) { + // Ignores the category anyways + return this.dcnpgettext.call( this, domain, undef, key ); + }, + + ngettext : function ( skey, pkey, val ) { + return this.dcnpgettext.call( this, undef, undef, skey, pkey, val ); + }, + + dngettext : function ( domain, skey, pkey, val ) { + return this.dcnpgettext.call( this, domain, undef, skey, pkey, val ); + }, + + dcngettext : function ( domain, skey, pkey, val/*, category */) { + return this.dcnpgettext.call( this, domain, undef, skey, pkey, val ); + }, + + pgettext : function ( context, key ) { + return this.dcnpgettext.call( this, undef, context, key ); + }, + + dpgettext : function ( domain, context, key ) { + return this.dcnpgettext.call( this, domain, context, key ); + }, + + dcpgettext : function ( domain, context, key/*, category */) { + return this.dcnpgettext.call( this, domain, context, key ); + }, + + npgettext : function ( context, skey, pkey, val ) { + return this.dcnpgettext.call( this, undef, context, skey, pkey, val ); + }, + + dnpgettext : function ( domain, context, skey, pkey, val ) { + return this.dcnpgettext.call( this, domain, context, skey, pkey, val ); + }, + + // The most fully qualified gettext function. It has every option. + // Since it has every option, we can use it from every other method. + // This is the bread and butter. + // Technically there should be one more argument in this function for 'Category', + // but since we never use it, we might as well not waste the bytes to define it. + dcnpgettext : function ( domain, context, singular_key, plural_key, val ) { + // Set some defaults + + plural_key = plural_key || singular_key; + + // Use the global domain default if one + // isn't explicitly passed in + domain = domain || this._textdomain; + + var fallback; + + // Handle special cases + + // No options found + if ( ! this.options ) { + // There's likely something wrong, but we'll return the correct key for english + // We do this by instantiating a brand new Jed instance with the default set + // for everything that could be broken. + fallback = new Jed(); + return fallback.dcnpgettext.call( fallback, undefined, undefined, singular_key, plural_key, val ); + } + + // No translation data provided + if ( ! this.options.locale_data ) { + throw new Error('No locale data provided.'); + } + + if ( ! this.options.locale_data[ domain ] ) { + throw new Error('Domain `' + domain + '` was not found.'); + } + + if ( ! this.options.locale_data[ domain ][ "" ] ) { + throw new Error('No locale meta information provided.'); + } + + // Make sure we have a truthy key. Otherwise we might start looking + // into the empty string key, which is the options for the locale + // data. + if ( ! singular_key ) { + throw new Error('No translation key found.'); + } + + var key = context ? context + Jed.context_delimiter + singular_key : singular_key, + locale_data = this.options.locale_data, + dict = locale_data[ domain ], + defaultConf = (locale_data.messages || this.defaults.locale_data.messages)[""], + pluralForms = dict[""].plural_forms || dict[""]["Plural-Forms"] || dict[""]["plural-forms"] || defaultConf.plural_forms || defaultConf["Plural-Forms"] || defaultConf["plural-forms"], + val_list, + res; + + var val_idx; + if (val === undefined) { + // No value passed in; assume singular key lookup. + val_idx = 0; + + } else { + // Value has been passed in; use plural-forms calculations. + + // Handle invalid numbers, but try casting strings for good measure + if ( typeof val != 'number' ) { + val = parseInt( val, 10 ); + + if ( isNaN( val ) ) { + throw new Error('The number that was passed in is not a number.'); + } + } + + val_idx = getPluralFormFunc(pluralForms)(val); + } + + // Throw an error if a domain isn't found + if ( ! dict ) { + throw new Error('No domain named `' + domain + '` could be found.'); + } + + val_list = dict[ key ]; + + // If there is no match, then revert back to + // english style singular/plural with the keys passed in. + if ( ! val_list || val_idx > val_list.length ) { + if (this.options.missing_key_callback) { + this.options.missing_key_callback(key, domain); + } + res = [ singular_key, plural_key ]; + + // collect untranslated strings + if (this.options.debug===true) { + console.log(res[ getPluralFormFunc(pluralForms)( val ) ]); + } + return res[ getPluralFormFunc()( val ) ]; + } + + res = val_list[ val_idx ]; + + // This includes empty strings on purpose + if ( ! res ) { + res = [ singular_key, plural_key ]; + return res[ getPluralFormFunc()( val ) ]; + } + return res; + } + }); + + + // We add in sprintf capabilities for post translation value interolation + // This is not internally used, so you can remove it if you have this + // available somewhere else, or want to use a different system. + + // We _slightly_ modify the normal sprintf behavior to more gracefully handle + // undefined values. + + /** + sprintf() for JavaScript 0.7-beta1 + http://www.diveintojavascript.com/projects/javascript-sprintf + + Copyright (c) Alexandru Marasteanu <alexaholic [at) gmail (dot] com> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of sprintf() for JavaScript nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL Alexandru Marasteanu BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + var sprintf = (function() { + function get_type(variable) { + return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase(); + } + function str_repeat(input, multiplier) { + for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */} + return output.join(''); + } + + var str_format = function() { + if (!str_format.cache.hasOwnProperty(arguments[0])) { + str_format.cache[arguments[0]] = str_format.parse(arguments[0]); + } + return str_format.format.call(null, str_format.cache[arguments[0]], arguments); + }; + + str_format.format = function(parse_tree, argv) { + var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length; + for (i = 0; i < tree_length; i++) { + node_type = get_type(parse_tree[i]); + if (node_type === 'string') { + output.push(parse_tree[i]); + } + else if (node_type === 'array') { + match = parse_tree[i]; // convenience purposes only + if (match[2]) { // keyword argument + arg = argv[cursor]; + for (k = 0; k < match[2].length; k++) { + if (!arg.hasOwnProperty(match[2][k])) { + throw(sprintf('[sprintf] property "%s" does not exist', match[2][k])); + } + arg = arg[match[2][k]]; + } + } + else if (match[1]) { // positional argument (explicit) + arg = argv[match[1]]; + } + else { // positional argument (implicit) + arg = argv[cursor++]; + } + + if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) { + throw(sprintf('[sprintf] expecting number but found %s', get_type(arg))); + } + + // Jed EDIT + if ( typeof arg == 'undefined' || arg === null ) { + arg = ''; + } + // Jed EDIT + + switch (match[8]) { + case 'b': arg = arg.toString(2); break; + case 'c': arg = String.fromCharCode(arg); break; + case 'd': arg = parseInt(arg, 10); break; + case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break; + case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break; + case 'o': arg = arg.toString(8); break; + case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break; + case 'u': arg = Math.abs(arg); break; + case 'x': arg = arg.toString(16); break; + case 'X': arg = arg.toString(16).toUpperCase(); break; + } + arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg); + pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' '; + pad_length = match[6] - String(arg).length; + pad = match[6] ? str_repeat(pad_character, pad_length) : ''; + output.push(match[5] ? arg + pad : pad + arg); + } + } + return output.join(''); + }; + + str_format.cache = {}; + + str_format.parse = function(fmt) { + var _fmt = fmt, match = [], parse_tree = [], arg_names = 0; + while (_fmt) { + if ((match = /^[^\x25]+/.exec(_fmt)) !== null) { + parse_tree.push(match[0]); + } + else if ((match = /^\x25{2}/.exec(_fmt)) !== null) { + parse_tree.push('%'); + } + else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) { + if (match[2]) { + arg_names |= 1; + var field_list = [], replacement_field = match[2], field_match = []; + if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') { + if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + } + else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) { + field_list.push(field_match[1]); + } + else { + throw('[sprintf] huh?'); + } + } + } + else { + throw('[sprintf] huh?'); + } + match[2] = field_list; + } + else { + arg_names |= 2; + } + if (arg_names === 3) { + throw('[sprintf] mixing positional and named placeholders is not (yet) supported'); + } + parse_tree.push(match); + } + else { + throw('[sprintf] huh?'); + } + _fmt = _fmt.substring(match[0].length); + } + return parse_tree; + }; + + return str_format; + })(); + + var vsprintf = function(fmt, argv) { + argv.unshift(fmt); + return sprintf.apply(null, argv); + }; + + Jed.parse_plural = function ( plural_forms, n ) { + plural_forms = plural_forms.replace(/n/g, n); + return Jed.parse_expression(plural_forms); + }; + + Jed.sprintf = function ( fmt, args ) { + if ( {}.toString.call( args ) == '[object Array]' ) { + return vsprintf( fmt, [].slice.call(args) ); + } + return sprintf.apply(this, [].slice.call(arguments) ); + }; + + Jed.prototype.sprintf = function () { + return Jed.sprintf.apply(this, arguments); + }; + // END sprintf Implementation + + // Start the Plural forms section + // This is a full plural form expression parser. It is used to avoid + // running 'eval' or 'new Function' directly against the plural + // forms. + // + // This can be important if you get translations done through a 3rd + // party vendor. I encourage you to use this instead, however, I + // also will provide a 'precompiler' that you can use at build time + // to output valid/safe function representations of the plural form + // expressions. This means you can build this code out for the most + // part. + Jed.PF = {}; + + Jed.PF.parse = function ( p ) { + var plural_str = Jed.PF.extractPluralExpr( p ); + return Jed.PF.parser.parse.call(Jed.PF.parser, plural_str); + }; + + Jed.PF.compile = function ( p ) { + // Handle trues and falses as 0 and 1 + function imply( val ) { + return (val === true ? 1 : val ? val : 0); + } + + var ast = Jed.PF.parse( p ); + return function ( n ) { + return imply( Jed.PF.interpreter( ast )( n ) ); + }; + }; + + Jed.PF.interpreter = function ( ast ) { + return function ( n ) { + var res; + switch ( ast.type ) { + case 'GROUP': + return Jed.PF.interpreter( ast.expr )( n ); + case 'TERNARY': + if ( Jed.PF.interpreter( ast.expr )( n ) ) { + return Jed.PF.interpreter( ast.truthy )( n ); + } + return Jed.PF.interpreter( ast.falsey )( n ); + case 'OR': + return Jed.PF.interpreter( ast.left )( n ) || Jed.PF.interpreter( ast.right )( n ); + case 'AND': + return Jed.PF.interpreter( ast.left )( n ) && Jed.PF.interpreter( ast.right )( n ); + case 'LT': + return Jed.PF.interpreter( ast.left )( n ) < Jed.PF.interpreter( ast.right )( n ); + case 'GT': + return Jed.PF.interpreter( ast.left )( n ) > Jed.PF.interpreter( ast.right )( n ); + case 'LTE': + return Jed.PF.interpreter( ast.left )( n ) <= Jed.PF.interpreter( ast.right )( n ); + case 'GTE': + return Jed.PF.interpreter( ast.left )( n ) >= Jed.PF.interpreter( ast.right )( n ); + case 'EQ': + return Jed.PF.interpreter( ast.left )( n ) == Jed.PF.interpreter( ast.right )( n ); + case 'NEQ': + return Jed.PF.interpreter( ast.left )( n ) != Jed.PF.interpreter( ast.right )( n ); + case 'MOD': + return Jed.PF.interpreter( ast.left )( n ) % Jed.PF.interpreter( ast.right )( n ); + case 'VAR': + return n; + case 'NUM': + return ast.val; + default: + throw new Error("Invalid Token found."); + } + }; + }; + + Jed.PF.regexps = { + TRIM_BEG: /^\s\s*/, + TRIM_END: /\s\s*$/, + HAS_SEMICOLON: /;\s*$/, + NPLURALS: /nplurals\=(\d+);/, + PLURAL: /plural\=(.*);/ + }; + + Jed.PF.extractPluralExpr = function ( p ) { + // trim first + p = p.replace(Jed.PF.regexps.TRIM_BEG, '').replace(Jed.PF.regexps.TRIM_END, ''); + + if (! Jed.PF.regexps.HAS_SEMICOLON.test(p)) { + p = p.concat(';'); + } + + var nplurals_matches = p.match( Jed.PF.regexps.NPLURALS ), + res = {}, + plural_matches; + + // Find the nplurals number + if ( nplurals_matches.length > 1 ) { + res.nplurals = nplurals_matches[1]; + } + else { + throw new Error('nplurals not found in plural_forms string: ' + p ); + } + + // remove that data to get to the formula + p = p.replace( Jed.PF.regexps.NPLURALS, "" ); + plural_matches = p.match( Jed.PF.regexps.PLURAL ); + + if (!( plural_matches && plural_matches.length > 1 ) ) { + throw new Error('`plural` expression not found: ' + p); + } + return plural_matches[ 1 ]; + }; + + /* Jison generated parser */ + Jed.PF.parser = (function(){ + +var parser = {trace: function trace() { }, +yy: {}, +symbols_: {"error":2,"expressions":3,"e":4,"EOF":5,"?":6,":":7,"||":8,"&&":9,"<":10,"<=":11,">":12,">=":13,"!=":14,"==":15,"%":16,"(":17,")":18,"n":19,"NUMBER":20,"$accept":0,"$end":1}, +terminals_: {2:"error",5:"EOF",6:"?",7:":",8:"||",9:"&&",10:"<",11:"<=",12:">",13:">=",14:"!=",15:"==",16:"%",17:"(",18:")",19:"n",20:"NUMBER"}, +productions_: [0,[3,2],[4,5],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,1],[4,1]], +performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) { + +var $0 = $$.length - 1; +switch (yystate) { +case 1: return { type : 'GROUP', expr: $$[$0-1] }; +break; +case 2:this.$ = { type: 'TERNARY', expr: $$[$0-4], truthy : $$[$0-2], falsey: $$[$0] }; +break; +case 3:this.$ = { type: "OR", left: $$[$0-2], right: $$[$0] }; +break; +case 4:this.$ = { type: "AND", left: $$[$0-2], right: $$[$0] }; +break; +case 5:this.$ = { type: 'LT', left: $$[$0-2], right: $$[$0] }; +break; +case 6:this.$ = { type: 'LTE', left: $$[$0-2], right: $$[$0] }; +break; +case 7:this.$ = { type: 'GT', left: $$[$0-2], right: $$[$0] }; +break; +case 8:this.$ = { type: 'GTE', left: $$[$0-2], right: $$[$0] }; +break; +case 9:this.$ = { type: 'NEQ', left: $$[$0-2], right: $$[$0] }; +break; +case 10:this.$ = { type: 'EQ', left: $$[$0-2], right: $$[$0] }; +break; +case 11:this.$ = { type: 'MOD', left: $$[$0-2], right: $$[$0] }; +break; +case 12:this.$ = { type: 'GROUP', expr: $$[$0-1] }; +break; +case 13:this.$ = { type: 'VAR' }; +break; +case 14:this.$ = { type: 'NUM', val: Number(yytext) }; +break; +} +}, +table: [{3:1,4:2,17:[1,3],19:[1,4],20:[1,5]},{1:[3]},{5:[1,6],6:[1,7],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16]},{4:17,17:[1,3],19:[1,4],20:[1,5]},{5:[2,13],6:[2,13],7:[2,13],8:[2,13],9:[2,13],10:[2,13],11:[2,13],12:[2,13],13:[2,13],14:[2,13],15:[2,13],16:[2,13],18:[2,13]},{5:[2,14],6:[2,14],7:[2,14],8:[2,14],9:[2,14],10:[2,14],11:[2,14],12:[2,14],13:[2,14],14:[2,14],15:[2,14],16:[2,14],18:[2,14]},{1:[2,1]},{4:18,17:[1,3],19:[1,4],20:[1,5]},{4:19,17:[1,3],19:[1,4],20:[1,5]},{4:20,17:[1,3],19:[1,4],20:[1,5]},{4:21,17:[1,3],19:[1,4],20:[1,5]},{4:22,17:[1,3],19:[1,4],20:[1,5]},{4:23,17:[1,3],19:[1,4],20:[1,5]},{4:24,17:[1,3],19:[1,4],20:[1,5]},{4:25,17:[1,3],19:[1,4],20:[1,5]},{4:26,17:[1,3],19:[1,4],20:[1,5]},{4:27,17:[1,3],19:[1,4],20:[1,5]},{6:[1,7],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[1,28]},{6:[1,7],7:[1,29],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16]},{5:[2,3],6:[2,3],7:[2,3],8:[2,3],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,3]},{5:[2,4],6:[2,4],7:[2,4],8:[2,4],9:[2,4],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,4]},{5:[2,5],6:[2,5],7:[2,5],8:[2,5],9:[2,5],10:[2,5],11:[2,5],12:[2,5],13:[2,5],14:[2,5],15:[2,5],16:[1,16],18:[2,5]},{5:[2,6],6:[2,6],7:[2,6],8:[2,6],9:[2,6],10:[2,6],11:[2,6],12:[2,6],13:[2,6],14:[2,6],15:[2,6],16:[1,16],18:[2,6]},{5:[2,7],6:[2,7],7:[2,7],8:[2,7],9:[2,7],10:[2,7],11:[2,7],12:[2,7],13:[2,7],14:[2,7],15:[2,7],16:[1,16],18:[2,7]},{5:[2,8],6:[2,8],7:[2,8],8:[2,8],9:[2,8],10:[2,8],11:[2,8],12:[2,8],13:[2,8],14:[2,8],15:[2,8],16:[1,16],18:[2,8]},{5:[2,9],6:[2,9],7:[2,9],8:[2,9],9:[2,9],10:[2,9],11:[2,9],12:[2,9],13:[2,9],14:[2,9],15:[2,9],16:[1,16],18:[2,9]},{5:[2,10],6:[2,10],7:[2,10],8:[2,10],9:[2,10],10:[2,10],11:[2,10],12:[2,10],13:[2,10],14:[2,10],15:[2,10],16:[1,16],18:[2,10]},{5:[2,11],6:[2,11],7:[2,11],8:[2,11],9:[2,11],10:[2,11],11:[2,11],12:[2,11],13:[2,11],14:[2,11],15:[2,11],16:[2,11],18:[2,11]},{5:[2,12],6:[2,12],7:[2,12],8:[2,12],9:[2,12],10:[2,12],11:[2,12],12:[2,12],13:[2,12],14:[2,12],15:[2,12],16:[2,12],18:[2,12]},{4:30,17:[1,3],19:[1,4],20:[1,5]},{5:[2,2],6:[1,7],7:[2,2],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,2]}], +defaultActions: {6:[2,1]}, +parseError: function parseError(str, hash) { + throw new Error(str); +}, +parse: function parse(input) { + var self = this, + stack = [0], + vstack = [null], // semantic value stack + lstack = [], // location stack + table = this.table, + yytext = '', + yylineno = 0, + yyleng = 0, + recovering = 0, + TERROR = 2, + EOF = 1; + + //this.reductionCount = this.shiftCount = 0; + + this.lexer.setInput(input); + this.lexer.yy = this.yy; + this.yy.lexer = this.lexer; + if (typeof this.lexer.yylloc == 'undefined') + this.lexer.yylloc = {}; + var yyloc = this.lexer.yylloc; + lstack.push(yyloc); + + if (typeof this.yy.parseError === 'function') + this.parseError = this.yy.parseError; + + function popStack (n) { + stack.length = stack.length - 2*n; + vstack.length = vstack.length - n; + lstack.length = lstack.length - n; + } + + function lex() { + var token; + token = self.lexer.lex() || 1; // $end = 1 + // if token isn't its numeric value, convert + if (typeof token !== 'number') { + token = self.symbols_[token] || token; + } + return token; + } + + var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected; + while (true) { + // retrieve state number from top of stack + state = stack[stack.length-1]; + + // use default actions if available + if (this.defaultActions[state]) { + action = this.defaultActions[state]; + } else { + if (symbol == null) + symbol = lex(); + // read action for current state and first input + action = table[state] && table[state][symbol]; + } + + // handle parse error + _handle_error: + if (typeof action === 'undefined' || !action.length || !action[0]) { + + if (!recovering) { + // Report error + expected = []; + for (p in table[state]) if (this.terminals_[p] && p > 2) { + expected.push("'"+this.terminals_[p]+"'"); + } + var errStr = ''; + if (this.lexer.showPosition) { + errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + this.terminals_[symbol]+ "'"; + } else { + errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " + + (symbol == 1 /*EOF*/ ? "end of input" : + ("'"+(this.terminals_[symbol] || symbol)+"'")); + } + this.parseError(errStr, + {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected}); + } + + // just recovered from another error + if (recovering == 3) { + if (symbol == EOF) { + throw new Error(errStr || 'Parsing halted.'); + } + + // discard current lookahead and grab another + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + symbol = lex(); + } + + // try to recover from error + while (1) { + // check for error recovery rule in this state + if ((TERROR.toString()) in table[state]) { + break; + } + if (state == 0) { + throw new Error(errStr || 'Parsing halted.'); + } + popStack(1); + state = stack[stack.length-1]; + } + + preErrorSymbol = symbol; // save the lookahead token + symbol = TERROR; // insert generic error symbol as new lookahead + state = stack[stack.length-1]; + action = table[state] && table[state][TERROR]; + recovering = 3; // allow 3 real symbols to be shifted before reporting a new error + } + + // this shouldn't happen, unless resolve defaults are off + if (action[0] instanceof Array && action.length > 1) { + throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol); + } + + switch (action[0]) { + + case 1: // shift + //this.shiftCount++; + + stack.push(symbol); + vstack.push(this.lexer.yytext); + lstack.push(this.lexer.yylloc); + stack.push(action[1]); // push state + symbol = null; + if (!preErrorSymbol) { // normal execution/no error + yyleng = this.lexer.yyleng; + yytext = this.lexer.yytext; + yylineno = this.lexer.yylineno; + yyloc = this.lexer.yylloc; + if (recovering > 0) + recovering--; + } else { // error just occurred, resume old lookahead f/ before error + symbol = preErrorSymbol; + preErrorSymbol = null; + } + break; + + case 2: // reduce + //this.reductionCount++; + + len = this.productions_[action[1]][1]; + + // perform semantic action + yyval.$ = vstack[vstack.length-len]; // default to $$ = $1 + // default location, uses first token for firsts, last for lasts + yyval._$ = { + first_line: lstack[lstack.length-(len||1)].first_line, + last_line: lstack[lstack.length-1].last_line, + first_column: lstack[lstack.length-(len||1)].first_column, + last_column: lstack[lstack.length-1].last_column + }; + r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); + + if (typeof r !== 'undefined') { + return r; + } + + // pop off stack + if (len) { + stack = stack.slice(0,-1*len*2); + vstack = vstack.slice(0, -1*len); + lstack = lstack.slice(0, -1*len); + } + + stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce) + vstack.push(yyval.$); + lstack.push(yyval._$); + // goto new state = table[STATE][NONTERMINAL] + newState = table[stack[stack.length-2]][stack[stack.length-1]]; + stack.push(newState); + break; + + case 3: // accept + return true; + } + + } + + return true; +}};/* Jison generated lexer */ +var lexer = (function(){ + +var lexer = ({EOF:1, +parseError:function parseError(str, hash) { + if (this.yy.parseError) { + this.yy.parseError(str, hash); + } else { + throw new Error(str); + } + }, +setInput:function (input) { + this._input = input; + this._more = this._less = this.done = false; + this.yylineno = this.yyleng = 0; + this.yytext = this.matched = this.match = ''; + this.conditionStack = ['INITIAL']; + this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0}; + return this; + }, +input:function () { + var ch = this._input[0]; + this.yytext+=ch; + this.yyleng++; + this.match+=ch; + this.matched+=ch; + var lines = ch.match(/\n/); + if (lines) this.yylineno++; + this._input = this._input.slice(1); + return ch; + }, +unput:function (ch) { + this._input = ch + this._input; + return this; + }, +more:function () { + this._more = true; + return this; + }, +pastInput:function () { + var past = this.matched.substr(0, this.matched.length - this.match.length); + return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); + }, +upcomingInput:function () { + var next = this.match; + if (next.length < 20) { + next += this._input.substr(0, 20-next.length); + } + return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, ""); + }, +showPosition:function () { + var pre = this.pastInput(); + var c = new Array(pre.length + 1).join("-"); + return pre + this.upcomingInput() + "\n" + c+"^"; + }, +next:function () { + if (this.done) { + return this.EOF; + } + if (!this._input) this.done = true; + + var token, + match, + col, + lines; + if (!this._more) { + this.yytext = ''; + this.match = ''; + } + var rules = this._currentRules(); + for (var i=0;i < rules.length; i++) { + match = this._input.match(this.rules[rules[i]]); + if (match) { + lines = match[0].match(/\n.*/g); + if (lines) this.yylineno += lines.length; + this.yylloc = {first_line: this.yylloc.last_line, + last_line: this.yylineno+1, + first_column: this.yylloc.last_column, + last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length} + this.yytext += match[0]; + this.match += match[0]; + this.matches = match; + this.yyleng = this.yytext.length; + this._more = false; + this._input = this._input.slice(match[0].length); + this.matched += match[0]; + token = this.performAction.call(this, this.yy, this, rules[i],this.conditionStack[this.conditionStack.length-1]); + if (token) return token; + else return; + } + } + if (this._input === "") { + return this.EOF; + } else { + this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(), + {text: "", token: null, line: this.yylineno}); + } + }, +lex:function lex() { + var r = this.next(); + if (typeof r !== 'undefined') { + return r; + } else { + return this.lex(); + } + }, +begin:function begin(condition) { + this.conditionStack.push(condition); + }, +popState:function popState() { + return this.conditionStack.pop(); + }, +_currentRules:function _currentRules() { + return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules; + }, +topState:function () { + return this.conditionStack[this.conditionStack.length-2]; + }, +pushState:function begin(condition) { + this.begin(condition); + }}); +lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { + +var YYSTATE=YY_START; +switch($avoiding_name_collisions) { +case 0:/* skip whitespace */ +break; +case 1:return 20 +break; +case 2:return 19 +break; +case 3:return 8 +break; +case 4:return 9 +break; +case 5:return 6 +break; +case 6:return 7 +break; +case 7:return 11 +break; +case 8:return 13 +break; +case 9:return 10 +break; +case 10:return 12 +break; +case 11:return 14 +break; +case 12:return 15 +break; +case 13:return 16 +break; +case 14:return 17 +break; +case 15:return 18 +break; +case 16:return 5 +break; +case 17:return 'INVALID' +break; +} +}; +lexer.rules = [/^\s+/,/^[0-9]+(\.[0-9]+)?\b/,/^n\b/,/^\|\|/,/^&&/,/^\?/,/^:/,/^<=/,/^>=/,/^</,/^>/,/^!=/,/^==/,/^%/,/^\(/,/^\)/,/^$/,/^./]; +lexer.conditions = {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17],"inclusive":true}};return lexer;})() +parser.lexer = lexer; +return parser; +})(); +// End parser + + // Handle node, amd, and global systems + if (typeof exports !== 'undefined') { + if (typeof module !== 'undefined' && module.exports) { + exports = module.exports = Jed; + } + exports.Jed = Jed; + } + else { + if (typeof define === 'function' && define.amd) { + define(function() { + return Jed; + }); + } + // Leak a global regardless of module system + root['Jed'] = Jed; + } + +})(this); diff --git a/src/libclient/web-chatview/linkify-html.js b/src/libclient/web-chatview/linkify-html.js new file mode 100644 index 0000000000000000000000000000000000000000..1e5090c9e6856b3b4a2688345e33b244aee63e25 --- /dev/null +++ b/src/libclient/web-chatview/linkify-html.js @@ -0,0 +1,827 @@ +/* + * Copyright (c) 2016 SoapBox Innovations Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. +*/ + +'use strict'; + +;(function (window, linkify) { + var linkifyHtml = function (linkify) { + 'use strict'; + + var HTML5NamedCharRefs = {}; + + function EntityParser(named) { + this.named = named; + } + + var HEXCHARCODE = /^#[xX]([A-Fa-f0-9]+)$/; + var CHARCODE = /^#([0-9]+)$/; + var NAMED = /^([A-Za-z0-9]+)$/; + + EntityParser.prototype.parse = function (entity) { + if (!entity) { + return; + } + var matches = entity.match(HEXCHARCODE); + if (matches) { + return '&#x' + matches[1] + ';'; + } + matches = entity.match(CHARCODE); + if (matches) { + return '&#' + matches[1] + ';'; + } + matches = entity.match(NAMED); + if (matches) { + return '&' + matches[1] + ';'; + } + }; + + var WSP = /[\t\n\f ]/; + var ALPHA = /[A-Za-z]/; + var CRLF = /\r\n?/g; + + function isSpace(char) { + return WSP.test(char); + } + + function isAlpha(char) { + return ALPHA.test(char); + } + + function preprocessInput(input) { + return input.replace(CRLF, "\n"); + } + + function EventedTokenizer(delegate, entityParser) { + this.delegate = delegate; + this.entityParser = entityParser; + + this.state = null; + this.input = null; + + this.index = -1; + this.line = -1; + this.column = -1; + this.tagLine = -1; + this.tagColumn = -1; + + this.reset(); + } + + EventedTokenizer.prototype = { + reset: function reset() { + this.state = 'beforeData'; + this.input = ''; + + this.index = 0; + this.line = 1; + this.column = 0; + + this.tagLine = -1; + this.tagColumn = -1; + + this.delegate.reset(); + }, + + tokenize: function tokenize(input) { + this.reset(); + this.tokenizePart(input); + this.tokenizeEOF(); + }, + + tokenizePart: function tokenizePart(input) { + this.input += preprocessInput(input); + + while (this.index < this.input.length) { + this.states[this.state].call(this); + } + }, + + tokenizeEOF: function tokenizeEOF() { + this.flushData(); + }, + + flushData: function flushData() { + if (this.state === 'data') { + this.delegate.finishData(); + this.state = 'beforeData'; + } + }, + + peek: function peek() { + return this.input.charAt(this.index); + }, + + consume: function consume() { + var char = this.peek(); + + this.index++; + + if (char === "\n") { + this.line++; + this.column = 0; + } else { + this.column++; + } + + return char; + }, + + consumeCharRef: function consumeCharRef() { + var endIndex = this.input.indexOf(';', this.index); + if (endIndex === -1) { + return; + } + var entity = this.input.slice(this.index, endIndex); + var chars = this.entityParser.parse(entity); + if (chars) { + this.index = endIndex + 1; + return chars; + } + }, + + markTagStart: function markTagStart() { + this.tagLine = this.line; + this.tagColumn = this.column; + }, + + states: { + beforeData: function beforeData() { + var char = this.peek(); + + if (char === "<") { + this.state = 'tagOpen'; + this.markTagStart(); + this.consume(); + } else { + this.state = 'data'; + this.delegate.beginData(); + } + }, + + data: function data() { + var char = this.peek(); + + if (char === "<") { + this.delegate.finishData(); + this.state = 'tagOpen'; + this.markTagStart(); + this.consume(); + } else if (char === "&") { + this.consume(); + this.delegate.appendToData(this.consumeCharRef() || "&"); + } else { + this.consume(); + this.delegate.appendToData(char); + } + }, + + tagOpen: function tagOpen() { + var char = this.consume(); + + if (char === "!") { + this.state = 'markupDeclaration'; + } else if (char === "/") { + this.state = 'endTagOpen'; + } else if (isAlpha(char)) { + this.state = 'tagName'; + this.delegate.beginStartTag(); + this.delegate.appendToTagName(char.toLowerCase()); + } + }, + + markupDeclaration: function markupDeclaration() { + var char = this.consume(); + + if (char === "-" && this.input.charAt(this.index) === "-") { + this.index++; + this.state = 'commentStart'; + this.delegate.beginComment(); + } + }, + + commentStart: function commentStart() { + var char = this.consume(); + + if (char === "-") { + this.state = 'commentStartDash'; + } else if (char === ">") { + this.delegate.finishComment(); + this.state = 'beforeData'; + } else { + this.delegate.appendToCommentData(char); + this.state = 'comment'; + } + }, + + commentStartDash: function commentStartDash() { + var char = this.consume(); + + if (char === "-") { + this.state = 'commentEnd'; + } else if (char === ">") { + this.delegate.finishComment(); + this.state = 'beforeData'; + } else { + this.delegate.appendToCommentData("-"); + this.state = 'comment'; + } + }, + + comment: function comment() { + var char = this.consume(); + + if (char === "-") { + this.state = 'commentEndDash'; + } else { + this.delegate.appendToCommentData(char); + } + }, + + commentEndDash: function commentEndDash() { + var char = this.consume(); + + if (char === "-") { + this.state = 'commentEnd'; + } else { + this.delegate.appendToCommentData("-" + char); + this.state = 'comment'; + } + }, + + commentEnd: function commentEnd() { + var char = this.consume(); + + if (char === ">") { + this.delegate.finishComment(); + this.state = 'beforeData'; + } else { + this.delegate.appendToCommentData("--" + char); + this.state = 'comment'; + } + }, + + tagName: function tagName() { + var char = this.consume(); + + if (isSpace(char)) { + this.state = 'beforeAttributeName'; + } else if (char === "/") { + this.state = 'selfClosingStartTag'; + } else if (char === ">") { + this.delegate.finishTag(); + this.state = 'beforeData'; + } else { + this.delegate.appendToTagName(char); + } + }, + + beforeAttributeName: function beforeAttributeName() { + var char = this.consume(); + + if (isSpace(char)) { + return; + } else if (char === "/") { + this.state = 'selfClosingStartTag'; + } else if (char === ">") { + this.delegate.finishTag(); + this.state = 'beforeData'; + } else { + this.state = 'attributeName'; + this.delegate.beginAttribute(); + this.delegate.appendToAttributeName(char); + } + }, + + attributeName: function attributeName() { + var char = this.consume(); + + if (isSpace(char)) { + this.state = 'afterAttributeName'; + } else if (char === "/") { + this.delegate.beginAttributeValue(false); + this.delegate.finishAttributeValue(); + this.state = 'selfClosingStartTag'; + } else if (char === "=") { + this.state = 'beforeAttributeValue'; + } else if (char === ">") { + this.delegate.beginAttributeValue(false); + this.delegate.finishAttributeValue(); + this.delegate.finishTag(); + this.state = 'beforeData'; + } else { + this.delegate.appendToAttributeName(char); + } + }, + + afterAttributeName: function afterAttributeName() { + var char = this.consume(); + + if (isSpace(char)) { + return; + } else if (char === "/") { + this.delegate.beginAttributeValue(false); + this.delegate.finishAttributeValue(); + this.state = 'selfClosingStartTag'; + } else if (char === "=") { + this.state = 'beforeAttributeValue'; + } else if (char === ">") { + this.delegate.beginAttributeValue(false); + this.delegate.finishAttributeValue(); + this.delegate.finishTag(); + this.state = 'beforeData'; + } else { + this.delegate.beginAttributeValue(false); + this.delegate.finishAttributeValue(); + this.state = 'attributeName'; + this.delegate.beginAttribute(); + this.delegate.appendToAttributeName(char); + } + }, + + beforeAttributeValue: function beforeAttributeValue() { + var char = this.consume(); + + if (isSpace(char)) {} else if (char === '"') { + this.state = 'attributeValueDoubleQuoted'; + this.delegate.beginAttributeValue(true); + } else if (char === "'") { + this.state = 'attributeValueSingleQuoted'; + this.delegate.beginAttributeValue(true); + } else if (char === ">") { + this.delegate.beginAttributeValue(false); + this.delegate.finishAttributeValue(); + this.delegate.finishTag(); + this.state = 'beforeData'; + } else { + this.state = 'attributeValueUnquoted'; + this.delegate.beginAttributeValue(false); + this.delegate.appendToAttributeValue(char); + } + }, + + attributeValueDoubleQuoted: function attributeValueDoubleQuoted() { + var char = this.consume(); + + if (char === '"') { + this.delegate.finishAttributeValue(); + this.state = 'afterAttributeValueQuoted'; + } else if (char === "&") { + this.delegate.appendToAttributeValue(this.consumeCharRef('"') || "&"); + } else { + this.delegate.appendToAttributeValue(char); + } + }, + + attributeValueSingleQuoted: function attributeValueSingleQuoted() { + var char = this.consume(); + + if (char === "'") { + this.delegate.finishAttributeValue(); + this.state = 'afterAttributeValueQuoted'; + } else if (char === "&") { + this.delegate.appendToAttributeValue(this.consumeCharRef("'") || "&"); + } else { + this.delegate.appendToAttributeValue(char); + } + }, + + attributeValueUnquoted: function attributeValueUnquoted() { + var char = this.consume(); + + if (isSpace(char)) { + this.delegate.finishAttributeValue(); + this.state = 'beforeAttributeName'; + } else if (char === "&") { + this.delegate.appendToAttributeValue(this.consumeCharRef(">") || "&"); + } else if (char === ">") { + this.delegate.finishAttributeValue(); + this.delegate.finishTag(); + this.state = 'beforeData'; + } else { + this.delegate.appendToAttributeValue(char); + } + }, + + afterAttributeValueQuoted: function afterAttributeValueQuoted() { + var char = this.peek(); + + if (isSpace(char)) { + this.consume(); + this.state = 'beforeAttributeName'; + } else if (char === "/") { + this.consume(); + this.state = 'selfClosingStartTag'; + } else if (char === ">") { + this.consume(); + this.delegate.finishTag(); + this.state = 'beforeData'; + } else { + this.state = 'beforeAttributeName'; + } + }, + + selfClosingStartTag: function selfClosingStartTag() { + var char = this.peek(); + + if (char === ">") { + this.consume(); + this.delegate.markTagAsSelfClosing(); + this.delegate.finishTag(); + this.state = 'beforeData'; + } else { + this.state = 'beforeAttributeName'; + } + }, + + endTagOpen: function endTagOpen() { + var char = this.consume(); + + if (isAlpha(char)) { + this.state = 'tagName'; + this.delegate.beginEndTag(); + this.delegate.appendToTagName(char.toLowerCase()); + } + } + } + }; + + function Tokenizer(entityParser, options) { + this.token = null; + this.startLine = 1; + this.startColumn = 0; + this.options = options || {}; + this.tokenizer = new EventedTokenizer(this, entityParser); + } + + Tokenizer.prototype = { + tokenize: function tokenize(input) { + this.tokens = []; + this.tokenizer.tokenize(input); + return this.tokens; + }, + + tokenizePart: function tokenizePart(input) { + this.tokens = []; + this.tokenizer.tokenizePart(input); + return this.tokens; + }, + + tokenizeEOF: function tokenizeEOF() { + this.tokens = []; + this.tokenizer.tokenizeEOF(); + return this.tokens[0]; + }, + + reset: function reset() { + this.token = null; + this.startLine = 1; + this.startColumn = 0; + }, + + addLocInfo: function addLocInfo() { + if (this.options.loc) { + this.token.loc = { + start: { + line: this.startLine, + column: this.startColumn + }, + end: { + line: this.tokenizer.line, + column: this.tokenizer.column + } + }; + } + this.startLine = this.tokenizer.line; + this.startColumn = this.tokenizer.column; + }, + + // Data + + beginData: function beginData() { + this.token = { + type: 'Chars', + chars: '' + }; + this.tokens.push(this.token); + }, + + appendToData: function appendToData(char) { + this.token.chars += char; + }, + + finishData: function finishData() { + this.addLocInfo(); + }, + + // Comment + + beginComment: function beginComment() { + this.token = { + type: 'Comment', + chars: '' + }; + this.tokens.push(this.token); + }, + + appendToCommentData: function appendToCommentData(char) { + this.token.chars += char; + }, + + finishComment: function finishComment() { + this.addLocInfo(); + }, + + // Tags - basic + + beginStartTag: function beginStartTag() { + this.token = { + type: 'StartTag', + tagName: '', + attributes: [], + selfClosing: false + }; + this.tokens.push(this.token); + }, + + beginEndTag: function beginEndTag() { + this.token = { + type: 'EndTag', + tagName: '' + }; + this.tokens.push(this.token); + }, + + finishTag: function finishTag() { + this.addLocInfo(); + }, + + markTagAsSelfClosing: function markTagAsSelfClosing() { + this.token.selfClosing = true; + }, + + // Tags - name + + appendToTagName: function appendToTagName(char) { + this.token.tagName += char; + }, + + // Tags - attributes + + beginAttribute: function beginAttribute() { + this._currentAttribute = ["", "", null]; + this.token.attributes.push(this._currentAttribute); + }, + + appendToAttributeName: function appendToAttributeName(char) { + this._currentAttribute[0] += char; + }, + + beginAttributeValue: function beginAttributeValue(isQuoted) { + this._currentAttribute[2] = isQuoted; + }, + + appendToAttributeValue: function appendToAttributeValue(char) { + this._currentAttribute[1] = this._currentAttribute[1] || ""; + this._currentAttribute[1] += char; + }, + + finishAttributeValue: function finishAttributeValue() {} + }; + + function tokenize(input, options) { + var tokenizer = new Tokenizer(new EntityParser(HTML5NamedCharRefs), options); + return tokenizer.tokenize(input); + } + + var HTML5Tokenizer = { + HTML5NamedCharRefs: HTML5NamedCharRefs, + EntityParser: EntityParser, + EventedTokenizer: EventedTokenizer, + Tokenizer: Tokenizer, + tokenize: tokenize + }; + + var options = linkify.options; + var Options = options.Options; + + + var StartTag = 'StartTag'; + var EndTag = 'EndTag'; + var Chars = 'Chars'; + var Comment = 'Comment'; + + /** + `tokens` and `token` in this section refer to tokens generated by the HTML + parser. + */ + function linkifyHtml(str) { + var opts = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + + var tokens = HTML5Tokenizer.tokenize(str); + var linkifiedTokens = []; + var linkified = []; + var i; + + opts = new Options(opts); + + // Linkify the tokens given by the parser + for (i = 0; i < tokens.length; i++) { + var token = tokens[i]; + + if (token.type === StartTag) { + linkifiedTokens.push(token); + + // Ignore all the contents of ignored tags + var tagName = token.tagName.toUpperCase(); + var isIgnored = tagName === 'A' || options.contains(opts.ignoreTags, tagName); + if (!isIgnored) { + continue; + } + + var preskipLen = linkifiedTokens.length; + skipTagTokens(tagName, tokens, ++i, linkifiedTokens); + i += linkifiedTokens.length - preskipLen - 1; + continue; + } else if (token.type !== Chars) { + // Skip this token, it's not important + linkifiedTokens.push(token); + continue; + } + + // Valid text token, linkify it! + var linkifedChars = linkifyChars(token.chars, opts); + linkifiedTokens.push.apply(linkifiedTokens, linkifedChars); + } + + // Convert the tokens back into a string + for (i = 0; i < linkifiedTokens.length; i++) { + var _token = linkifiedTokens[i]; + switch (_token.type) { + case StartTag: + var link = '<' + _token.tagName; + if (_token.attributes.length > 0) { + var attrs = attrsToStrings(_token.attributes); + link += ' ' + attrs.join(' '); + } + link += '>'; + linkified.push(link); + break; + case EndTag: + linkified.push('</' + _token.tagName + '>'); + break; + case Chars: + linkified.push(escapeText(_token.chars)); + break; + case Comment: + linkified.push('<!--' + escapeText(_token.chars) + '-->'); + break; + } + } + + return linkified.join(''); + } + + /** + `tokens` and `token` in this section referes to tokens returned by + `linkify.tokenize`. `linkified` will contain HTML Parser-style tokens + */ + function linkifyChars(str, opts) { + var tokens = linkify.tokenize(str); + var result = []; + + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + + if (token.type === 'nl' && opts.nl2br) { + result.push({ + type: StartTag, + tagName: 'br', + attributes: [], + selfClosing: true + }); + continue; + } else if (!token.isLink || !opts.check(token)) { + result.push({ type: Chars, chars: token.toString() }); + continue; + } + + var _opts$resolve = opts.resolve(token); + + var href = _opts$resolve.href; + var formatted = _opts$resolve.formatted; + var formattedHref = _opts$resolve.formattedHref; + var tagName = _opts$resolve.tagName; + var className = _opts$resolve.className; + var target = _opts$resolve.target; + var attributes = _opts$resolve.attributes; + + // Build up attributes + + var attributeArray = [['href', formattedHref]]; + + if (className) { + attributeArray.push(['class', className]); + } + + if (target) { + attributeArray.push(['target', target]); + } + + for (var attr in attributes) { + attributeArray.push([attr, attributes[attr]]); + } + + // Add the required tokens + result.push({ + type: StartTag, + tagName: tagName, + attributes: attributeArray, + selfClosing: false + }); + result.push({ type: Chars, chars: formatted }); + result.push({ type: EndTag, tagName: tagName }); + } + + return result; + } + + /** + Returns a list of tokens skipped until the closing tag of tagName. + + * `tagName` is the closing tag which will prompt us to stop skipping + * `tokens` is the array of tokens generated by HTML5Tokenizer which + * `i` is the index immediately after the opening tag to skip + * `skippedTokens` is an array which skipped tokens are being pushed into + + Caveats + + * Assumes that i is the first token after the given opening tagName + * The closing tag will be skipped, but nothing after it + * Will track whether there is a nested tag of the same type + */ + function skipTagTokens(tagName, tokens, i, skippedTokens) { + + // number of tokens of this type on the [fictional] stack + var stackCount = 1; + + while (i < tokens.length && stackCount > 0) { + var token = tokens[i]; + if (token.type === StartTag && token.tagName.toUpperCase() === tagName) { + // Nested tag of the same type, "add to stack" + stackCount++; + } else if (token.type === EndTag && token.tagName.toUpperCase() === tagName) { + // Closing tag + stackCount--; + } + skippedTokens.push(token); + i++; + } + + // Note that if stackCount > 0 here, the HTML is probably invalid + return skippedTokens; + } + + function escapeText(text) { + // Not required, HTML tokenizer ensures this occurs properly + return text; + } + + function escapeAttr(attr) { + return attr.replace(/"/g, '"'); + } + + function attrsToStrings(attrs) { + var attrStrs = []; + for (var i = 0; i < attrs.length; i++) { + var _attrs$i = attrs[i]; + var name = _attrs$i[0]; + var value = _attrs$i[1]; + + attrStrs.push(name + '="' + escapeAttr(value) + '"'); + } + return attrStrs; + } + + return linkifyHtml; + }(linkify); + window.linkifyHtml = linkifyHtml; +})(window, linkify); diff --git a/src/libclient/web-chatview/linkify-string.js b/src/libclient/web-chatview/linkify-string.js new file mode 100644 index 0000000000000000000000000000000000000000..699a94d1f47ac7fbc6d1c3dfbd51cc553d12feed --- /dev/null +++ b/src/libclient/web-chatview/linkify-string.js @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2016 SoapBox Innovations Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. +*/ + +'use strict'; + +;(function (window, linkify) { + var linkifyString = function (linkify) { + 'use strict'; + + /** + Convert strings of text into linkable HTML text + */ + + var tokenize = linkify.tokenize; + var options = linkify.options; + var Options = options.Options; + + + function escapeText(text) { + return text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); + } + + function escapeAttr(href) { + return href.replace(/"/g, '"'); + } + + function attributesToString(attributes) { + if (!attributes) { + return ''; + } + var result = []; + + for (var attr in attributes) { + var val = attributes[attr] + ''; + result.push(attr + '="' + escapeAttr(val) + '"'); + } + return result.join(' '); + } + + function linkifyStr(str) { + var opts = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1]; + + opts = new Options(opts); + + var tokens = tokenize(str); + var result = []; + + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + + if (token.type === 'nl' && opts.nl2br) { + result.push('<br>\n'); + continue; + } else if (!token.isLink || !opts.check(token)) { + result.push(escapeText(token.toString())); + continue; + } + + var _opts$resolve = opts.resolve(token); + + var formatted = _opts$resolve.formatted; + var formattedHref = _opts$resolve.formattedHref; + var tagName = _opts$resolve.tagName; + var className = _opts$resolve.className; + var target = _opts$resolve.target; + var attributes = _opts$resolve.attributes; + + + var link = '<' + tagName + ' href="' + escapeAttr(formattedHref) + '"'; + + if (className) { + link += ' class="' + escapeAttr(className) + '"'; + } + + if (target) { + link += ' target="' + escapeAttr(target) + '"'; + } + + if (attributes) { + link += ' ' + attributesToString(attributes); + } + + link += '>' + escapeText(formatted) + '</' + tagName + '>'; + result.push(link); + } + + return result.join(''); + } + + if (!String.prototype.linkify) { + String.prototype.linkify = function (opts) { + return linkifyStr(this, opts); + }; + } + + return linkifyStr; + }(linkify); + window.linkifyStr = linkifyString; +})(window, linkify); diff --git a/src/libclient/web-chatview/linkify.js b/src/libclient/web-chatview/linkify.js new file mode 100644 index 0000000000000000000000000000000000000000..7666ff8aeb8b2e1960467601bc1a157b98b80f7b --- /dev/null +++ b/src/libclient/web-chatview/linkify.js @@ -0,0 +1,1271 @@ +/* + * Copyright (c) 2016 SoapBox Innovations Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. +*/ + +;(function () { +'use strict'; + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj; }; + +(function (exports) { + 'use strict'; + + function inherits(parent, child) { + var props = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; + + var extended = Object.create(parent.prototype); + for (var p in props) { + extended[p] = props[p]; + } + extended.constructor = child; + child.prototype = extended; + return child; + } + + var defaults = { + defaultProtocol: 'http', + events: null, + format: noop, + formatHref: noop, + nl2br: false, + tagName: 'a', + target: typeToTarget, + validate: true, + ignoreTags: [], + attributes: null, + className: 'linkified' }; + + function Options(opts) { + opts = opts || {}; + + this.defaultProtocol = opts.defaultProtocol || defaults.defaultProtocol; + this.events = opts.events || defaults.events; + this.format = opts.format || defaults.format; + this.formatHref = opts.formatHref || defaults.formatHref; + this.nl2br = opts.nl2br || defaults.nl2br; + this.tagName = opts.tagName || defaults.tagName; + this.target = opts.target || defaults.target; + this.validate = opts.validate || defaults.validate; + this.ignoreTags = []; + + // linkAttributes and linkClass is deprecated + this.attributes = opts.attributes || opts.linkAttributes || defaults.attributes; + this.className = opts.className || opts.linkClass || defaults.className; + + // Make all tags names upper case + + var ignoredTags = opts.ignoreTags || defaults.ignoreTags; + for (var i = 0; i < ignoredTags.length; i++) { + this.ignoreTags.push(ignoredTags[i].toUpperCase()); + } + } + + Options.prototype = { + /** + * Given the token, return all options for how it should be displayed + */ + resolve: function resolve(token) { + var href = token.toHref(this.defaultProtocol); + return { + formatted: this.get('format', token.toString(), token), + formattedHref: this.get('formatHref', href, token), + tagName: this.get('tagName', href, token), + className: this.get('className', href, token), + target: this.get('target', href, token), + events: this.getObject('events', href, token), + attributes: this.getObject('attributes', href, token) + }; + }, + + + /** + * Returns true or false based on whether a token should be displayed as a + * link based on the user options. By default, + */ + check: function check(token) { + return this.get('validate', token.toString(), token); + }, + + + // Private methods + + /** + * Resolve an option's value based on the value of the option and the given + * params. + * @param [String] key Name of option to use + * @param operator will be passed to the target option if it's method + * @param [MultiToken] token The token from linkify.tokenize + */ + get: function get(key, operator, token) { + var option = this[key]; + + if (!option) { + return option; + } + + switch (typeof option === 'undefined' ? 'undefined' : _typeof(option)) { + case 'function': + return option(operator, token.type); + case 'object': + var optionValue = option[token.type] || defaults[key]; + return typeof optionValue === 'function' ? optionValue(operator, token.type) : optionValue; + } + + return option; + }, + getObject: function getObject(key, operator, token) { + var option = this[key]; + return typeof option === 'function' ? option(operator, token.type) : option; + } + }; + + /** + * Quick indexOf replacement for checking the ignoreTags option + */ + function contains(arr, value) { + for (var i = 0; i < arr.length; i++) { + if (arr[i] === value) { + return true; + } + } + return false; + } + + function noop(val) { + return val; + } + + function typeToTarget(href, type) { + return type === 'url' ? '_blank' : null; + } + + var options = Object.freeze({ + defaults: defaults, + Options: Options, + contains: contains + }); + + function createStateClass() { + return function (tClass) { + this.j = []; + this.T = tClass || null; + }; + } + + /** + A simple state machine that can emit token classes + + The `j` property in this class refers to state jumps. It's a + multidimensional array where for each element: + + * index [0] is a symbol or class of symbols to transition to. + * index [1] is a State instance which matches + + The type of symbol will depend on the target implementation for this class. + In Linkify, we have a two-stage scanner. Each stage uses this state machine + but with a slighly different (polymorphic) implementation. + + The `T` property refers to the token class. + + TODO: Can the `on` and `next` methods be combined? + + @class BaseState + */ + var BaseState = createStateClass(); + BaseState.prototype = { + defaultTransition: false, + + /** + @method constructor + @param {Class} tClass Pass in the kind of token to emit if there are + no jumps after this state and the state is accepting. + */ + + /** + On the given symbol(s), this machine should go to the given state + @method on + @param {Array|Mixed} symbol + @param {BaseState} state Note that the type of this state should be the + same as the current instance (i.e., don't pass in a different + subclass) + */ + on: function on(symbol, state) { + if (symbol instanceof Array) { + for (var i = 0; i < symbol.length; i++) { + this.j.push([symbol[i], state]); + } + return this; + } + this.j.push([symbol, state]); + return this; + }, + + + /** + Given the next item, returns next state for that item + @method next + @param {Mixed} item Should be an instance of the symbols handled by + this particular machine. + @return {State} state Returns false if no jumps are available + */ + next: function next(item) { + for (var i = 0; i < this.j.length; i++) { + var jump = this.j[i]; + var symbol = jump[0]; // Next item to check for + var state = jump[1]; // State to jump to if items match + + // compare item with symbol + if (this.test(item, symbol)) { + return state; + } + } + + // Nowhere left to jump! + return this.defaultTransition; + }, + + + /** + Does this state accept? + `true` only of `this.T` exists + @method accepts + @return {Boolean} + */ + accepts: function accepts() { + return !!this.T; + }, + + + /** + Determine whether a given item "symbolizes" the symbol, where symbol is + a class of items handled by this state machine. + This method should be overridden in extended classes. + @method test + @param {Mixed} item Does this item match the given symbol? + @param {Mixed} symbol + @return {Boolean} + */ + test: function test(item, symbol) { + return item === symbol; + }, + + + /** + Emit the token for this State (just return it in this case) + If this emits a token, this instance is an accepting state + @method emit + @return {Class} T + */ + emit: function emit() { + return this.T; + } + }; + + /** + State machine for string-based input + + @class CharacterState + @extends BaseState + */ + var CharacterState = inherits(BaseState, createStateClass(), { + /** + Does the given character match the given character or regular + expression? + @method test + @param {String} char + @param {String|RegExp} charOrRegExp + @return {Boolean} + */ + test: function test(character, charOrRegExp) { + return character === charOrRegExp || charOrRegExp instanceof RegExp && charOrRegExp.test(character); + } + }); + + /** + State machine for input in the form of TextTokens + + @class TokenState + @extends BaseState + */ + var State = inherits(BaseState, createStateClass(), { + + /** + * Similar to `on`, but returns the state the results in the transition from + * the given item + * @method jump + * @param {Mixed} item + * @param {Token} [token] + * @return state + */ + jump: function jump(token) { + var tClass = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; + + var state = this.next(new token('')); // dummy temp token + if (state === this.defaultTransition) { + // Make a new state! + state = new this.constructor(tClass); + this.on(token, state); + } else if (tClass) { + state.T = tClass; + } + return state; + }, + + + /** + Is the given token an instance of the given token class? + @method test + @param {TextToken} token + @param {Class} tokenClass + @return {Boolean} + */ + test: function test(token, tokenClass) { + return token instanceof tokenClass; + } + }); + + /** + Given a non-empty target string, generates states (if required) for each + consecutive substring of characters in str starting from the beginning of + the string. The final state will have a special value, as specified in + options. All other "in between" substrings will have a default end state. + + This turns the state machine into a Trie-like data structure (rather than a + intelligently-designed DFA). + + Note that I haven't really tried these with any strings other than + DOMAIN. + + @param {String} str + @param {CharacterState} start State to jump from the first character + @param {Class} endToken Token class to emit when the given string has been + matched and no more jumps exist. + @param {Class} defaultToken "Filler token", or which token type to emit when + we don't have a full match + @return {Array} list of newly-created states + */ + function stateify(str, start, endToken, defaultToken) { + var i = 0, + len = str.length, + state = start, + newStates = [], + nextState = void 0; + + // Find the next state without a jump to the next character + while (i < len && (nextState = state.next(str[i]))) { + state = nextState; + i++; + } + + if (i >= len) { + return []; + } // no new tokens were added + + while (i < len - 1) { + nextState = new CharacterState(defaultToken); + newStates.push(nextState); + state.on(str[i], nextState); + state = nextState; + i++; + } + + nextState = new CharacterState(endToken); + newStates.push(nextState); + state.on(str[len - 1], nextState); + + return newStates; + } + + function createTokenClass() { + return function (value) { + if (value) { + this.v = value; + } + }; + } + + /****************************************************************************** + Text Tokens + Tokens composed of strings + ******************************************************************************/ + + /** + Abstract class used for manufacturing text tokens. + Pass in the value this token represents + + @class TextToken + @abstract + */ + var TextToken = createTokenClass(); + TextToken.prototype = { + toString: function toString() { + return this.v + ''; + } + }; + + function inheritsToken(value) { + var props = value ? { v: value } : {}; + return inherits(TextToken, createTokenClass(), props); + } + + /** + A valid domain token + @class DOMAIN + @extends TextToken + */ + var DOMAIN = inheritsToken(); + + /** + @class AT + @extends TextToken + */ + var AT = inheritsToken('@'); + + /** + Represents a single colon `:` character + + @class COLON + @extends TextToken + */ + var COLON = inheritsToken(':'); + + /** + @class DOT + @extends TextToken + */ + var DOT = inheritsToken('.'); + + /** + A character class that can surround the URL, but which the URL cannot begin + or end with. Does not include certain English punctuation like parentheses. + + @class PUNCTUATION + @extends TextToken + */ + var PUNCTUATION = inheritsToken(); + + /** + The word localhost (by itself) + @class LOCALHOST + @extends TextToken + */ + var LOCALHOST = inheritsToken(); + + /** + Newline token + @class NL + @extends TextToken + */ + var TNL = inheritsToken('\n'); + + /** + @class NUM + @extends TextToken + */ + var NUM = inheritsToken(); + + /** + @class PLUS + @extends TextToken + */ + var PLUS = inheritsToken('+'); + + /** + @class POUND + @extends TextToken + */ + var POUND = inheritsToken('#'); + + /** + Represents a web URL protocol. Supported types include + + * `http:` + * `https:` + * `ftp:` + * `ftps:` + * There's Another super weird one + + @class PROTOCOL + @extends TextToken + */ + var PROTOCOL = inheritsToken(); + + /** + @class QUERY + @extends TextToken + */ + var QUERY = inheritsToken('?'); + + /** + @class SLASH + @extends TextToken + */ + var SLASH = inheritsToken('/'); + + /** + @class UNDERSCORE + @extends TextToken + */ + var UNDERSCORE = inheritsToken('_'); + + /** + One ore more non-whitespace symbol. + @class SYM + @extends TextToken + */ + var SYM = inheritsToken(); + + /** + @class TLD + @extends TextToken + */ + var TLD = inheritsToken(); + + /** + Represents a string of consecutive whitespace characters + + @class WS + @extends TextToken + */ + var WS = inheritsToken(); + + /** + Opening/closing bracket classes + */ + + var OPENBRACE = inheritsToken('{'); + var OPENBRACKET = inheritsToken('['); + var OPENANGLEBRACKET = inheritsToken('<'); + var OPENPAREN = inheritsToken('('); + var CLOSEBRACE = inheritsToken('}'); + var CLOSEBRACKET = inheritsToken(']'); + var CLOSEANGLEBRACKET = inheritsToken('>'); + var CLOSEPAREN = inheritsToken(')'); + + var TOKENS = Object.freeze({ + Base: TextToken, + DOMAIN: DOMAIN, + AT: AT, + COLON: COLON, + DOT: DOT, + PUNCTUATION: PUNCTUATION, + LOCALHOST: LOCALHOST, + NL: TNL, + NUM: NUM, + PLUS: PLUS, + POUND: POUND, + QUERY: QUERY, + PROTOCOL: PROTOCOL, + SLASH: SLASH, + UNDERSCORE: UNDERSCORE, + SYM: SYM, + TLD: TLD, + WS: WS, + OPENBRACE: OPENBRACE, + OPENBRACKET: OPENBRACKET, + OPENANGLEBRACKET: OPENANGLEBRACKET, + OPENPAREN: OPENPAREN, + CLOSEBRACE: CLOSEBRACE, + CLOSEBRACKET: CLOSEBRACKET, + CLOSEANGLEBRACKET: CLOSEANGLEBRACKET, + CLOSEPAREN: CLOSEPAREN + }); + + /** + The scanner provides an interface that takes a string of text as input, and + outputs an array of tokens instances that can be used for easy URL parsing. + + @module linkify + @submodule scanner + @main scanner + */ + + var tlds = 'aaa|aarp|abb|abbott|abogado|ac|academy|accenture|accountant|accountants|aco|active|actor|ad|adac|ads|adult|ae|aeg|aero|af|afl|ag|agency|ai|aig|airforce|airtel|al|alibaba|alipay|allfinanz|alsace|am|amica|amsterdam|an|analytics|android|ao|apartments|app|apple|aq|aquarelle|ar|aramco|archi|army|arpa|arte|as|asia|associates|at|attorney|au|auction|audi|audio|author|auto|autos|avianca|aw|ax|axa|az|azure|ba|baidu|band|bank|bar|barcelona|barclaycard|barclays|bargains|bauhaus|bayern|bb|bbc|bbva|bcg|bcn|bd|be|beats|beer|bentley|berlin|best|bet|bf|bg|bh|bharti|bi|bible|bid|bike|bing|bingo|bio|biz|bj|black|blackfriday|bloomberg|blue|bm|bms|bmw|bn|bnl|bnpparibas|bo|boats|boehringer|bom|bond|boo|book|boots|bosch|bostik|bot|boutique|br|bradesco|bridgestone|broadway|broker|brother|brussels|bs|bt|budapest|bugatti|build|builders|business|buy|buzz|bv|bw|by|bz|bzh|ca|cab|cafe|cal|call|camera|camp|cancerresearch|canon|capetown|capital|car|caravan|cards|care|career|careers|cars|cartier|casa|cash|casino|cat|catering|cba|cbn|cc|cd|ceb|center|ceo|cern|cf|cfa|cfd|cg|ch|chanel|channel|chase|chat|cheap|chloe|christmas|chrome|church|ci|cipriani|circle|cisco|citic|city|cityeats|ck|cl|claims|cleaning|click|clinic|clinique|clothing|cloud|club|clubmed|cm|cn|co|coach|codes|coffee|college|cologne|com|commbank|community|company|compare|computer|comsec|condos|construction|consulting|contact|contractors|cooking|cool|coop|corsica|country|coupon|coupons|courses|cr|credit|creditcard|creditunion|cricket|crown|crs|cruises|csc|cu|cuisinella|cv|cw|cx|cy|cymru|cyou|cz|dabur|dad|dance|date|dating|datsun|day|dclk|de|dealer|deals|degree|delivery|dell|deloitte|delta|democrat|dental|dentist|desi|design|dev|diamonds|diet|digital|direct|directory|discount|dj|dk|dm|dnp|do|docs|dog|doha|domains|download|drive|dubai|durban|dvag|dz|earth|eat|ec|edeka|edu|education|ee|eg|email|emerck|energy|engineer|engineering|enterprises|epson|equipment|er|erni|es|esq|estate|et|eu|eurovision|eus|events|everbank|exchange|expert|exposed|express|fage|fail|fairwinds|faith|family|fan|fans|farm|fashion|fast|feedback|ferrero|fi|film|final|finance|financial|firestone|firmdale|fish|fishing|fit|fitness|fj|fk|flickr|flights|florist|flowers|flsmidth|fly|fm|fo|foo|football|ford|forex|forsale|forum|foundation|fox|fr|fresenius|frl|frogans|frontier|fund|furniture|futbol|fyi|ga|gal|gallery|gallup|game|garden|gb|gbiz|gd|gdn|ge|gea|gent|genting|gf|gg|ggee|gh|gi|gift|gifts|gives|giving|gl|glass|gle|global|globo|gm|gmail|gmbh|gmo|gmx|gn|gold|goldpoint|golf|goo|goog|google|gop|got|gov|gp|gq|gr|grainger|graphics|gratis|green|gripe|group|gs|gt|gu|gucci|guge|guide|guitars|guru|gw|gy|hamburg|hangout|haus|hdfcbank|health|healthcare|help|helsinki|here|hermes|hiphop|hitachi|hiv|hk|hm|hn|hockey|holdings|holiday|homedepot|homes|honda|horse|host|hosting|hoteles|hotmail|house|how|hr|hsbc|ht|hu|hyundai|ibm|icbc|ice|icu|id|ie|ifm|iinet|il|im|immo|immobilien|in|industries|infiniti|info|ing|ink|institute|insurance|insure|int|international|investments|io|ipiranga|iq|ir|irish|is|iselect|ist|istanbul|it|itau|iwc|jaguar|java|jcb|je|jetzt|jewelry|jlc|jll|jm|jmp|jo|jobs|joburg|jot|joy|jp|jpmorgan|jprs|juegos|kaufen|kddi|ke|kerryhotels|kerrylogistics|kerryproperties|kfh|kg|kh|ki|kia|kim|kinder|kitchen|kiwi|km|kn|koeln|komatsu|kp|kpn|kr|krd|kred|kuokgroup|kw|ky|kyoto|kz|la|lacaixa|lamborghini|lamer|lancaster|land|landrover|lanxess|lasalle|lat|latrobe|law|lawyer|lb|lc|lds|lease|leclerc|legal|lexus|lgbt|li|liaison|lidl|life|lifeinsurance|lifestyle|lighting|like|limited|limo|lincoln|linde|link|live|living|lixil|lk|loan|loans|local|locus|lol|london|lotte|lotto|love|lr|ls|lt|ltd|ltda|lu|lupin|luxe|luxury|lv|ly|ma|madrid|maif|maison|makeup|man|management|mango|market|marketing|markets|marriott|mba|mc|md|me|med|media|meet|melbourne|meme|memorial|men|menu|meo|mg|mh|miami|microsoft|mil|mini|mk|ml|mm|mma|mn|mo|mobi|mobily|moda|moe|moi|mom|monash|money|montblanc|mormon|mortgage|moscow|motorcycles|mov|movie|movistar|mp|mq|mr|ms|mt|mtn|mtpc|mtr|mu|museum|mutuelle|mv|mw|mx|my|mz|na|nadex|nagoya|name|natura|navy|nc|ne|nec|net|netbank|network|neustar|new|news|nexus|nf|ng|ngo|nhk|ni|nico|nikon|ninja|nissan|nl|no|nokia|norton|nowruz|np|nr|nra|nrw|ntt|nu|nyc|nz|obi|office|okinawa|om|omega|one|ong|onl|online|ooo|oracle|orange|org|organic|origins|osaka|otsuka|ovh|pa|page|pamperedchef|panerai|paris|pars|partners|parts|party|passagens|pe|pet|pf|pg|ph|pharmacy|philips|photo|photography|photos|physio|piaget|pics|pictet|pictures|pid|pin|ping|pink|pizza|pk|pl|place|play|playstation|plumbing|plus|pm|pn|pohl|poker|porn|post|pr|praxi|press|pro|prod|productions|prof|promo|properties|property|protection|ps|pt|pub|pw|pwc|py|qa|qpon|quebec|quest|racing|re|read|realtor|realty|recipes|red|redstone|redumbrella|rehab|reise|reisen|reit|ren|rent|rentals|repair|report|republican|rest|restaurant|review|reviews|rexroth|rich|ricoh|rio|rip|ro|rocher|rocks|rodeo|room|rs|rsvp|ru|ruhr|run|rw|rwe|ryukyu|sa|saarland|safe|safety|sakura|sale|salon|samsung|sandvik|sandvikcoromant|sanofi|sap|sapo|sarl|sas|saxo|sb|sbs|sc|sca|scb|schaeffler|schmidt|scholarships|school|schule|schwarz|science|scor|scot|sd|se|seat|security|seek|select|sener|services|seven|sew|sex|sexy|sfr|sg|sh|sharp|shell|shia|shiksha|shoes|show|shriram|si|singles|site|sj|sk|ski|skin|sky|skype|sl|sm|smile|sn|sncf|so|soccer|social|softbank|software|sohu|solar|solutions|song|sony|soy|space|spiegel|spot|spreadbetting|sr|srl|st|stada|star|starhub|statefarm|statoil|stc|stcgroup|stockholm|storage|store|studio|study|style|su|sucks|supplies|supply|support|surf|surgery|suzuki|sv|swatch|swiss|sx|sy|sydney|symantec|systems|sz|tab|taipei|taobao|tatamotors|tatar|tattoo|tax|taxi|tc|tci|td|team|tech|technology|tel|telecity|telefonica|temasek|tennis|tf|tg|th|thd|theater|theatre|tickets|tienda|tiffany|tips|tires|tirol|tj|tk|tl|tm|tmall|tn|to|today|tokyo|tools|top|toray|toshiba|total|tours|town|toyota|toys|tp|tr|trade|trading|training|travel|travelers|travelersinsurance|trust|trv|tt|tube|tui|tunes|tushu|tv|tvs|tw|tz|ua|ubs|ug|uk|unicom|university|uno|uol|us|uy|uz|va|vacations|vana|vc|ve|vegas|ventures|verisign|versicherung|vet|vg|vi|viajes|video|viking|villas|vin|vip|virgin|vision|vista|vistaprint|viva|vlaanderen|vn|vodka|volkswagen|vote|voting|voto|voyage|vu|vuelos|wales|walter|wang|wanggou|watch|watches|weather|weatherchannel|webcam|weber|website|wed|wedding|weir|wf|whoswho|wien|wiki|williamhill|win|windows|wine|wme|wolterskluwer|work|works|world|ws|wtc|wtf|xbox|xerox|xin|xperia|xxx|xyz|yachts|yahoo|yamaxun|yandex|ye|yodobashi|yoga|yokohama|youtube|yt|za|zara|zero|zip|zm|zone|zuerich|zw'.split('|'); // macro, see gulpfile.js + + var NUMBERS = '0123456789'.split(''); + var ALPHANUM = '0123456789abcdefghijklmnopqrstuvwxyz'.split(''); + var WHITESPACE = [' ', '\f', '\r', '\t', '\v', ' ', ' ', 'á Ž']; // excluding line breaks + + var domainStates = []; // states that jump to DOMAIN on /[a-z0-9]/ + var makeState = function makeState(tokenClass) { + return new CharacterState(tokenClass); + }; + + // Frequently used states + var S_START = makeState(); + var S_NUM = makeState(NUM); + var S_DOMAIN = makeState(DOMAIN); + var S_DOMAIN_HYPHEN = makeState(); // domain followed by 1 or more hyphen characters + var S_WS = makeState(WS); + + // States for special URL symbols + S_START.on('@', makeState(AT)).on('.', makeState(DOT)).on('+', makeState(PLUS)).on('#', makeState(POUND)).on('?', makeState(QUERY)).on('/', makeState(SLASH)).on('_', makeState(UNDERSCORE)).on(':', makeState(COLON)).on('{', makeState(OPENBRACE)).on('[', makeState(OPENBRACKET)).on('<', makeState(OPENANGLEBRACKET)).on('(', makeState(OPENPAREN)).on('}', makeState(CLOSEBRACE)).on(']', makeState(CLOSEBRACKET)).on('>', makeState(CLOSEANGLEBRACKET)).on(')', makeState(CLOSEPAREN)).on([',', ';', '!', '"', '\''], makeState(PUNCTUATION)); + + // Whitespace jumps + // Tokens of only non-newline whitespace are arbitrarily long + S_START.on('\n', makeState(TNL)).on(WHITESPACE, S_WS); + + // If any whitespace except newline, more whitespace! + S_WS.on(WHITESPACE, S_WS); + + // Generates states for top-level domains + // Note that this is most accurate when tlds are in alphabetical order + for (var i = 0; i < tlds.length; i++) { + var newStates = stateify(tlds[i], S_START, TLD, DOMAIN); + domainStates.push.apply(domainStates, newStates); + } + + // Collect the states generated by different protocls + var partialProtocolFileStates = stateify('file', S_START, DOMAIN, DOMAIN); + var partialProtocolFtpStates = stateify('ftp', S_START, DOMAIN, DOMAIN); + var partialProtocolHttpStates = stateify('http', S_START, DOMAIN, DOMAIN); + + // Add the states to the array of DOMAINeric states + domainStates.push.apply(domainStates, partialProtocolFileStates); + domainStates.push.apply(domainStates, partialProtocolFtpStates); + domainStates.push.apply(domainStates, partialProtocolHttpStates); + + // Protocol states + var S_PROTOCOL_FILE = partialProtocolFileStates.pop(); + var S_PROTOCOL_FTP = partialProtocolFtpStates.pop(); + var S_PROTOCOL_HTTP = partialProtocolHttpStates.pop(); + var S_PROTOCOL_SECURE = makeState(DOMAIN); + var S_FULL_PROTOCOL = makeState(PROTOCOL); // Full protocol ends with COLON + + // Secure protocols (end with 's') + S_PROTOCOL_FTP.on('s', S_PROTOCOL_SECURE).on(':', S_FULL_PROTOCOL); + + S_PROTOCOL_HTTP.on('s', S_PROTOCOL_SECURE).on(':', S_FULL_PROTOCOL); + + domainStates.push(S_PROTOCOL_SECURE); + + // Become protocol tokens after a COLON + S_PROTOCOL_FILE.on(':', S_FULL_PROTOCOL); + S_PROTOCOL_SECURE.on(':', S_FULL_PROTOCOL); + + // Localhost + var partialLocalhostStates = stateify('localhost', S_START, LOCALHOST, DOMAIN); + domainStates.push.apply(domainStates, partialLocalhostStates); + + // Everything else + // DOMAINs make more DOMAINs + // Number and character transitions + S_START.on(NUMBERS, S_NUM); + S_NUM.on('-', S_DOMAIN_HYPHEN).on(NUMBERS, S_NUM).on(ALPHANUM, S_DOMAIN); // number becomes DOMAIN + + S_DOMAIN.on('-', S_DOMAIN_HYPHEN).on(ALPHANUM, S_DOMAIN); + + // All the generated states should have a jump to DOMAIN + for (var _i = 0; _i < domainStates.length; _i++) { + domainStates[_i].on('-', S_DOMAIN_HYPHEN).on(ALPHANUM, S_DOMAIN); + } + + S_DOMAIN_HYPHEN.on('-', S_DOMAIN_HYPHEN).on(NUMBERS, S_DOMAIN).on(ALPHANUM, S_DOMAIN); + + // Set default transition + S_START.defaultTransition = makeState(SYM); + + /** + Given a string, returns an array of TOKEN instances representing the + composition of that string. + + @method run + @param {String} str Input string to scan + @return {Array} Array of TOKEN instances + */ + var run = function run(str) { + + // The state machine only looks at lowercase strings. + // This selective `toLowerCase` is used because lowercasing the entire + // string causes the length and character position to vary in some in some + // non-English strings. This happens only on V8-based runtimes. + var lowerStr = str.replace(/[A-Z]/g, function (c) { + return c.toLowerCase(); + }); + var len = str.length; + var tokens = []; // return value + + var cursor = 0; + + // Tokenize the string + while (cursor < len) { + var state = S_START; + var secondState = null; + var nextState = null; + var tokenLength = 0; + var latestAccepting = null; + var sinceAccepts = -1; + + while (cursor < len && (nextState = state.next(lowerStr[cursor]))) { + secondState = null; + state = nextState; + + // Keep track of the latest accepting state + if (state.accepts()) { + sinceAccepts = 0; + latestAccepting = state; + } else if (sinceAccepts >= 0) { + sinceAccepts++; + } + + tokenLength++; + cursor++; + } + + if (sinceAccepts < 0) { + continue; + } // Should never happen + + // Roll back to the latest accepting state + cursor -= sinceAccepts; + tokenLength -= sinceAccepts; + + // Get the class for the new token + var TOKEN = latestAccepting.emit(); // Current token class + + // No more jumps, just make a new token + tokens.push(new TOKEN(str.substr(cursor - tokenLength, tokenLength))); + } + + return tokens; + }; + + var start = S_START; + + var scanner = Object.freeze({ + State: CharacterState, + TOKENS: TOKENS, + run: run, + start: start + }); + + /****************************************************************************** + Multi-Tokens + Tokens composed of arrays of TextTokens + ******************************************************************************/ + + // Is the given token a valid domain token? + // Should nums be included here? + function isDomainToken(token) { + return token instanceof DOMAIN || token instanceof TLD; + } + + /** + Abstract class used for manufacturing tokens of text tokens. That is rather + than the value for a token being a small string of text, it's value an array + of text tokens. + + Used for grouping together URLs, emails, hashtags, and other potential + creations. + + @class MultiToken + @abstract + */ + var MultiToken = createTokenClass(); + + MultiToken.prototype = { + /** + String representing the type for this token + @property type + @default 'TOKEN' + */ + type: 'token', + + /** + Is this multitoken a link? + @property isLink + @default false + */ + isLink: false, + + /** + Return the string this token represents. + @method toString + @return {String} + */ + toString: function toString() { + var result = []; + for (var _i2 = 0; _i2 < this.v.length; _i2++) { + result.push(this.v[_i2].toString()); + } + return result.join(''); + }, + + + /** + What should the value for this token be in the `href` HTML attribute? + Returns the `.toString` value by default. + @method toHref + @return {String} + */ + toHref: function toHref() { + return this.toString(); + }, + + + /** + Returns a hash of relevant values for this token, which includes keys + * type - Kind of token ('url', 'email', etc.) + * value - Original text + * href - The value that should be added to the anchor tag's href + attribute + @method toObject + @param {String} [protocol] `'http'` by default + @return {Object} + */ + toObject: function toObject() { + var protocol = arguments.length <= 0 || arguments[0] === undefined ? 'http' : arguments[0]; + + return { + type: this.type, + value: this.toString(), + href: this.toHref(protocol) + }; + } + }; + + /** + Represents a list of tokens making up a valid email address + @class EMAIL + @extends MultiToken + */ + var EMAIL = inherits(MultiToken, createTokenClass(), { + type: 'email', + isLink: true, + toHref: function toHref() { + return 'mailto:' + this.toString(); + } + }); + + /** + Represents some plain text + @class TEXT + @extends MultiToken + */ + var TEXT = inherits(MultiToken, createTokenClass(), { type: 'text' }); + + /** + Multi-linebreak token - represents a line break + @class NL + @extends MultiToken + */ + var NL = inherits(MultiToken, createTokenClass(), { type: 'nl' }); + + /** + Represents a list of tokens making up a valid URL + @class URL + @extends MultiToken + */ + var URL = inherits(MultiToken, createTokenClass(), { + type: 'url', + isLink: true, + + /** + Lowercases relevant parts of the domain and adds the protocol if + required. Note that this will not escape unsafe HTML characters in the + URL. + @method href + @param {String} protocol + @return {String} + */ + toHref: function toHref() { + var protocol = arguments.length <= 0 || arguments[0] === undefined ? 'http' : arguments[0]; + + var hasProtocol = false; + var hasSlashSlash = false; + var tokens = this.v; + var result = []; + var i = 0; + + // Make the first part of the domain lowercase + // Lowercase protocol + while (tokens[i] instanceof PROTOCOL) { + hasProtocol = true; + result.push(tokens[i].toString().toLowerCase()); + i++; + } + + // Skip slash-slash + while (tokens[i] instanceof SLASH) { + hasSlashSlash = true; + result.push(tokens[i].toString()); + i++; + } + + // Lowercase all other characters in the domain + while (isDomainToken(tokens[i])) { + result.push(tokens[i].toString().toLowerCase()); + i++; + } + + // Leave all other characters as they were written + for (; i < tokens.length; i++) { + result.push(tokens[i].toString()); + } + + result = result.join(''); + + if (!(hasProtocol || hasSlashSlash)) { + result = protocol + '://' + result; + } + + return result; + }, + hasProtocol: function hasProtocol() { + return this.v[0] instanceof PROTOCOL; + } + }); + + var TOKENS$1 = Object.freeze({ + Base: MultiToken, + EMAIL: EMAIL, + NL: NL, + TEXT: TEXT, + URL: URL + }); + + /** + Not exactly parser, more like the second-stage scanner (although we can + theoretically hotswap the code here with a real parser in the future... but + for a little URL-finding utility abstract syntax trees may be a little + overkill). + + URL format: http://en.wikipedia.org/wiki/URI_scheme + Email format: http://en.wikipedia.org/wiki/Email_address (links to RFC in + reference) + + @module linkify + @submodule parser + @main parser + */ + + var makeState$1 = function makeState$1(tokenClass) { + return new State(tokenClass); + }; + + // The universal starting state. + var S_START$1 = makeState$1(); + + // Intermediate states for URLs. Note that domains that begin with a protocol + // are treated slighly differently from those that don't. + var S_PROTOCOL = makeState$1(); // e.g., 'http:' + var S_PROTOCOL_SLASH = makeState$1(); // e.g., '/', 'http:/'' + var S_PROTOCOL_SLASH_SLASH = makeState$1(); // e.g., '//', 'http://' + var S_DOMAIN$1 = makeState$1(); // parsed string ends with a potential domain name (A) + var S_DOMAIN_DOT = makeState$1(); // (A) domain followed by DOT + var S_TLD = makeState$1(URL); // (A) Simplest possible URL with no query string + var S_TLD_COLON = makeState$1(); // (A) URL followed by colon (potential port number here) + var S_TLD_PORT = makeState$1(URL); // TLD followed by a port number + var S_URL = makeState$1(URL); // Long URL with optional port and maybe query string + var S_URL_NON_ACCEPTING = makeState$1(); // URL followed by some symbols (will not be part of the final URL) + var S_URL_OPENBRACE = makeState$1(); // URL followed by { + var S_URL_OPENBRACKET = makeState$1(); // URL followed by [ + var S_URL_OPENANGLEBRACKET = makeState$1(); // URL followed by < + var S_URL_OPENPAREN = makeState$1(); // URL followed by ( + var S_URL_OPENBRACE_Q = makeState$1(URL); // URL followed by { and some symbols that the URL can end it + var S_URL_OPENBRACKET_Q = makeState$1(URL); // URL followed by [ and some symbols that the URL can end it + var S_URL_OPENANGLEBRACKET_Q = makeState$1(URL); // URL followed by < and some symbols that the URL can end it + var S_URL_OPENPAREN_Q = makeState$1(URL); // URL followed by ( and some symbols that the URL can end it + var S_URL_OPENBRACE_SYMS = makeState$1(); // S_URL_OPENBRACE_Q followed by some symbols it cannot end it + var S_URL_OPENBRACKET_SYMS = makeState$1(); // S_URL_OPENBRACKET_Q followed by some symbols it cannot end it + var S_URL_OPENANGLEBRACKET_SYMS = makeState$1(); // S_URL_OPENANGLEBRACKET_Q followed by some symbols it cannot end it + var S_URL_OPENPAREN_SYMS = makeState$1(); // S_URL_OPENPAREN_Q followed by some symbols it cannot end it + var S_EMAIL_DOMAIN = makeState$1(); // parsed string starts with local email info + @ with a potential domain name (C) + var S_EMAIL_DOMAIN_DOT = makeState$1(); // (C) domain followed by DOT + var S_EMAIL = makeState$1(EMAIL); // (C) Possible email address (could have more tlds) + var S_EMAIL_COLON = makeState$1(); // (C) URL followed by colon (potential port number here) + var S_EMAIL_PORT = makeState$1(EMAIL); // (C) Email address with a port + var S_LOCALPART = makeState$1(); // Local part of the email address + var S_LOCALPART_AT = makeState$1(); // Local part of the email address plus @ + var S_LOCALPART_DOT = makeState$1(); // Local part of the email address plus '.' (localpart cannot end in .) + var S_NL = makeState$1(NL); // single new line + + // Make path from start to protocol (with '//') + S_START$1.on(TNL, S_NL).on(PROTOCOL, S_PROTOCOL).on(SLASH, S_PROTOCOL_SLASH); + + S_PROTOCOL.on(SLASH, S_PROTOCOL_SLASH); + S_PROTOCOL_SLASH.on(SLASH, S_PROTOCOL_SLASH_SLASH); + + // The very first potential domain name + S_START$1.on(TLD, S_DOMAIN$1).on(DOMAIN, S_DOMAIN$1).on(LOCALHOST, S_TLD).on(NUM, S_DOMAIN$1); + + // Force URL for anything sane followed by protocol + S_PROTOCOL_SLASH_SLASH.on(TLD, S_URL).on(DOMAIN, S_URL).on(NUM, S_URL).on(LOCALHOST, S_URL); + + // Account for dots and hyphens + // hyphens are usually parts of domain names + S_DOMAIN$1.on(DOT, S_DOMAIN_DOT); + S_EMAIL_DOMAIN.on(DOT, S_EMAIL_DOMAIN_DOT); + + // Hyphen can jump back to a domain name + + // After the first domain and a dot, we can find either a URL or another domain + S_DOMAIN_DOT.on(TLD, S_TLD).on(DOMAIN, S_DOMAIN$1).on(NUM, S_DOMAIN$1).on(LOCALHOST, S_DOMAIN$1); + + S_EMAIL_DOMAIN_DOT.on(TLD, S_EMAIL).on(DOMAIN, S_EMAIL_DOMAIN).on(NUM, S_EMAIL_DOMAIN).on(LOCALHOST, S_EMAIL_DOMAIN); + + // S_TLD accepts! But the URL could be longer, try to find a match greedily + // The `run` function should be able to "rollback" to the accepting state + S_TLD.on(DOT, S_DOMAIN_DOT); + S_EMAIL.on(DOT, S_EMAIL_DOMAIN_DOT); + + // Become real URLs after `SLASH` or `COLON NUM SLASH` + // Here PSS and non-PSS converge + S_TLD.on(COLON, S_TLD_COLON).on(SLASH, S_URL); + S_TLD_COLON.on(NUM, S_TLD_PORT); + S_TLD_PORT.on(SLASH, S_URL); + S_EMAIL.on(COLON, S_EMAIL_COLON); + S_EMAIL_COLON.on(NUM, S_EMAIL_PORT); + + // Types of characters the URL can definitely end in + var qsAccepting = [DOMAIN, AT, LOCALHOST, NUM, PLUS, POUND, PROTOCOL, SLASH, TLD, UNDERSCORE, SYM]; + + // Types of tokens that can follow a URL and be part of the query string + // but cannot be the very last characters + // Characters that cannot appear in the URL at all should be excluded + var qsNonAccepting = [COLON, DOT, QUERY, PUNCTUATION, CLOSEBRACE, CLOSEBRACKET, CLOSEANGLEBRACKET, CLOSEPAREN, OPENBRACE, OPENBRACKET, OPENANGLEBRACKET, OPENPAREN]; + + // These states are responsible primarily for determining whether or not to + // include the final round bracket. + + // URL, followed by an opening bracket + S_URL.on(OPENBRACE, S_URL_OPENBRACE).on(OPENBRACKET, S_URL_OPENBRACKET).on(OPENANGLEBRACKET, S_URL_OPENANGLEBRACKET).on(OPENPAREN, S_URL_OPENPAREN); + + // URL with extra symbols at the end, followed by an opening bracket + S_URL_NON_ACCEPTING.on(OPENBRACE, S_URL_OPENBRACE).on(OPENBRACKET, S_URL_OPENBRACKET).on(OPENANGLEBRACKET, S_URL_OPENANGLEBRACKET).on(OPENPAREN, S_URL_OPENPAREN); + + // Closing bracket component. This character WILL be included in the URL + S_URL_OPENBRACE.on(CLOSEBRACE, S_URL); + S_URL_OPENBRACKET.on(CLOSEBRACKET, S_URL); + S_URL_OPENANGLEBRACKET.on(CLOSEANGLEBRACKET, S_URL); + S_URL_OPENPAREN.on(CLOSEPAREN, S_URL); + S_URL_OPENBRACE_Q.on(CLOSEBRACE, S_URL); + S_URL_OPENBRACKET_Q.on(CLOSEBRACKET, S_URL); + S_URL_OPENANGLEBRACKET_Q.on(CLOSEANGLEBRACKET, S_URL); + S_URL_OPENPAREN_Q.on(CLOSEPAREN, S_URL); + S_URL_OPENBRACE_SYMS.on(CLOSEBRACE, S_URL); + S_URL_OPENBRACKET_SYMS.on(CLOSEBRACKET, S_URL); + S_URL_OPENANGLEBRACKET_SYMS.on(CLOSEANGLEBRACKET, S_URL); + S_URL_OPENPAREN_SYMS.on(CLOSEPAREN, S_URL); + + // URL that beings with an opening bracket, followed by a symbols. + // Note that the final state can still be `S_URL_OPENBRACE_Q` (if the URL only + // has a single opening bracket for some reason). + S_URL_OPENBRACE.on(qsAccepting, S_URL_OPENBRACE_Q); + S_URL_OPENBRACKET.on(qsAccepting, S_URL_OPENBRACKET_Q); + S_URL_OPENANGLEBRACKET.on(qsAccepting, S_URL_OPENANGLEBRACKET_Q); + S_URL_OPENPAREN.on(qsAccepting, S_URL_OPENPAREN_Q); + S_URL_OPENBRACE.on(qsNonAccepting, S_URL_OPENBRACE_SYMS); + S_URL_OPENBRACKET.on(qsNonAccepting, S_URL_OPENBRACKET_SYMS); + S_URL_OPENANGLEBRACKET.on(qsNonAccepting, S_URL_OPENANGLEBRACKET_SYMS); + S_URL_OPENPAREN.on(qsNonAccepting, S_URL_OPENPAREN_SYMS); + + // URL that begins with an opening bracket, followed by some symbols + S_URL_OPENBRACE_Q.on(qsAccepting, S_URL_OPENBRACE_Q); + S_URL_OPENBRACKET_Q.on(qsAccepting, S_URL_OPENBRACKET_Q); + S_URL_OPENANGLEBRACKET_Q.on(qsAccepting, S_URL_OPENANGLEBRACKET_Q); + S_URL_OPENPAREN_Q.on(qsAccepting, S_URL_OPENPAREN_Q); + S_URL_OPENBRACE_Q.on(qsNonAccepting, S_URL_OPENBRACE_Q); + S_URL_OPENBRACKET_Q.on(qsNonAccepting, S_URL_OPENBRACKET_Q); + S_URL_OPENANGLEBRACKET_Q.on(qsNonAccepting, S_URL_OPENANGLEBRACKET_Q); + S_URL_OPENPAREN_Q.on(qsNonAccepting, S_URL_OPENPAREN_Q); + + S_URL_OPENBRACE_SYMS.on(qsAccepting, S_URL_OPENBRACE_Q); + S_URL_OPENBRACKET_SYMS.on(qsAccepting, S_URL_OPENBRACKET_Q); + S_URL_OPENANGLEBRACKET_SYMS.on(qsAccepting, S_URL_OPENANGLEBRACKET_Q); + S_URL_OPENPAREN_SYMS.on(qsAccepting, S_URL_OPENPAREN_Q); + S_URL_OPENBRACE_SYMS.on(qsNonAccepting, S_URL_OPENBRACE_SYMS); + S_URL_OPENBRACKET_SYMS.on(qsNonAccepting, S_URL_OPENBRACKET_SYMS); + S_URL_OPENANGLEBRACKET_SYMS.on(qsNonAccepting, S_URL_OPENANGLEBRACKET_SYMS); + S_URL_OPENPAREN_SYMS.on(qsNonAccepting, S_URL_OPENPAREN_SYMS); + + // Account for the query string + S_URL.on(qsAccepting, S_URL); + S_URL_NON_ACCEPTING.on(qsAccepting, S_URL); + + S_URL.on(qsNonAccepting, S_URL_NON_ACCEPTING); + S_URL_NON_ACCEPTING.on(qsNonAccepting, S_URL_NON_ACCEPTING); + + // Email address-specific state definitions + // Note: We are not allowing '/' in email addresses since this would interfere + // with real URLs + + // Tokens allowed in the localpart of the email + var localpartAccepting = [DOMAIN, NUM, PLUS, POUND, QUERY, UNDERSCORE, SYM, TLD]; + + // Some of the tokens in `localpartAccepting` are already accounted for here and + // will not be overwritten (don't worry) + S_DOMAIN$1.on(localpartAccepting, S_LOCALPART).on(AT, S_LOCALPART_AT); + S_TLD.on(localpartAccepting, S_LOCALPART).on(AT, S_LOCALPART_AT); + S_DOMAIN_DOT.on(localpartAccepting, S_LOCALPART); + + // Okay we're on a localpart. Now what? + // TODO: IP addresses and what if the email starts with numbers? + S_LOCALPART.on(localpartAccepting, S_LOCALPART).on(AT, S_LOCALPART_AT) // close to an email address now + .on(DOT, S_LOCALPART_DOT); + S_LOCALPART_DOT.on(localpartAccepting, S_LOCALPART); + S_LOCALPART_AT.on(TLD, S_EMAIL_DOMAIN).on(DOMAIN, S_EMAIL_DOMAIN).on(LOCALHOST, S_EMAIL); + // States following `@` defined above + + var run$1 = function run$1(tokens) { + var len = tokens.length; + var cursor = 0; + var multis = []; + var textTokens = []; + + while (cursor < len) { + var state = S_START$1; + var secondState = null; + var nextState = null; + var multiLength = 0; + var latestAccepting = null; + var sinceAccepts = -1; + + while (cursor < len && !(secondState = state.next(tokens[cursor]))) { + // Starting tokens with nowhere to jump to. + // Consider these to be just plain text + textTokens.push(tokens[cursor++]); + } + + while (cursor < len && (nextState = secondState || state.next(tokens[cursor]))) { + + // Get the next state + secondState = null; + state = nextState; + + // Keep track of the latest accepting state + if (state.accepts()) { + sinceAccepts = 0; + latestAccepting = state; + } else if (sinceAccepts >= 0) { + sinceAccepts++; + } + + cursor++; + multiLength++; + } + + if (sinceAccepts < 0) { + + // No accepting state was found, part of a regular text token + // Add all the tokens we looked at to the text tokens array + for (var _i3 = cursor - multiLength; _i3 < cursor; _i3++) { + textTokens.push(tokens[_i3]); + } + } else { + + // Accepting state! + + // First close off the textTokens (if available) + if (textTokens.length > 0) { + multis.push(new TEXT(textTokens)); + textTokens = []; + } + + // Roll back to the latest accepting state + cursor -= sinceAccepts; + multiLength -= sinceAccepts; + + // Create a new multitoken + var MULTI = latestAccepting.emit(); + multis.push(new MULTI(tokens.slice(cursor - multiLength, cursor))); + } + } + + // Finally close off the textTokens (if available) + if (textTokens.length > 0) { + multis.push(new TEXT(textTokens)); + } + + return multis; + }; + + var parser = Object.freeze({ + State: State, + TOKENS: TOKENS$1, + run: run$1, + start: S_START$1 + }); + + if (!Array.isArray) { + Array.isArray = function (arg) { + return Object.prototype.toString.call(arg) === '[object Array]'; + }; + } + + /** + Converts a string into tokens that represent linkable and non-linkable bits + @method tokenize + @param {String} str + @return {Array} tokens + */ + var tokenize = function tokenize(str) { + return run$1(run(str)); + }; + + /** + Returns a list of linkable items in the given string. + */ + var find = function find(str) { + var type = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; + + var tokens = tokenize(str); + var filtered = []; + + for (var i = 0; i < tokens.length; i++) { + var token = tokens[i]; + if (token.isLink && (!type || token.type === type)) { + filtered.push(token.toObject()); + } + } + + return filtered; + }; + + /** + Is the given string valid linkable text of some sort + Note that this does not trim the text for you. + + Optionally pass in a second `type` param, which is the type of link to test + for. + + For example, + + test(str, 'email'); + + Will return `true` if str is a valid email. + */ + var test = function test(str) { + var type = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; + + var tokens = tokenize(str); + return tokens.length === 1 && tokens[0].isLink && (!type || tokens[0].type === type); + }; + + exports.find = find; + exports.inherits = inherits; + exports.options = options; + exports.parser = parser; + exports.scanner = scanner; + exports.test = test; + exports.tokenize = tokenize; +})(window.linkify = window.linkify || {}); +})(); diff --git a/src/libclient/web-chatview/previewInfo.js b/src/libclient/web-chatview/previewInfo.js new file mode 100644 index 0000000000000000000000000000000000000000..83a14cae92775ce08436f8c09b6420bb2ec82a33 --- /dev/null +++ b/src/libclient/web-chatview/previewInfo.js @@ -0,0 +1,126 @@ +/* MIT License + +Copyright (c) 2019 Andrej Gajdos + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.*/ + +/** + * Retrieves the title of a webpage which is used to fill out the preview of a hyperlink + * @param doc the DOM of the url that is being previewed + * @returns the title of the given webpage + */ + +function getTitle(doc){ + const og_title = doc.querySelector('meta[property="og:title"]') + if (og_title !== null && og_title.content.length > 0) { + return og_title.content + } + const twitter_title = doc.querySelector('meta[name="twitter:title"]') + if (twitter_title !== null && twitter_title.content.length > 0) { + return twitter_title.content + } + const doc_title = doc.title + if (doc_title !== null && doc_title.length > 0) { + return doc_title + } + if (doc.querySelector("h1") !== null){ + const header_1 = doc.querySelector("h1").innerHTML + if (header_1 !== null && header_1.length > 0) { + return header_1 + } + } + if (doc.querySelector("h2") !== null){ + const header_2 = doc.querySelector("h2").innerHTML + if (header_2 !== null && header_2.length > 0) { + return header_2 + } + } + return null +} + +/** + * Obtains a description of the webpage for the hyperlink preview + * @param doc the DOM of the url that is being previewed + * @returns a description of the webpage + */ +function getDescription(doc){ + const og_description = doc.querySelector('meta[property="og:description"]') + if (og_description !== null && og_description.content.length > 0) { + return og_description.content + } + const twitter_description = doc.querySelector('meta[name="twitter:description"]') + if (twitter_description !== null && twitter_description.content.length > 0) { + return twitter_description.content + } + const meta_description = doc.querySelector('meta[name="description"]') + if (meta_description !== null && meta_description.content.length > 0) { + return meta_description.content + } + var all_paragraphs = doc.querySelectorAll("p") + let first_visible_paragraph = null + for (var i = 0; i < all_paragraphs.length; i++) { + if (all_paragraphs[i].offsetParent !== null && + !all_paragraphs[i].childElementCount !== 0) { + first_visible_paragraph = all_paragraphs[i].textContent + break + } + } + return first_visible_paragraph +} + +/** + * Gets the image that represents a webpage. + * @param doc the DOM of the url that is being previewed + * @returns the image representing the url or null if no such image was found + */ +function getImage(doc) { + const og_image = doc.querySelector('meta[property="og:image"]') + if (og_image !== null && og_image.content.length > 0){ + return og_image.content + } + const image_rel_link = doc.querySelector('link[rel="image_src"]') + if (image_rel_link !== null && image_rel_link.href.length > 0){ + return image_rel_link.href + } + const twitter_img = doc.querySelector('meta[name="twitter:image"]') + if (twitter_img !== null && twitter_img.content.length > 0) { + return twitter_img.content + } + + let imgs = Array.from(doc.getElementsByTagName("img")) + if (imgs.length > 0) { + imgs = imgs.filter(img => { + let add_image = true + if (img.naturalWidth > img.naturalHeight) { + if (img.naturalWidth / img.naturalHeight > 3) { + add_image = false + } + } else { + if (img.naturalHeight / img.naturalWidth > 3) { + add_image = false + } + } + if (img.naturalHeight <= 50 || img.naturalWidth <= 50) { + add_image = false + } + return add_image + }) + } + return null +} diff --git a/src/libclient/web-chatview/qwebchannel.js b/src/libclient/web-chatview/qwebchannel.js new file mode 100644 index 0000000000000000000000000000000000000000..5b047c27b45d08e5dd6cd47930f6ec7962f8db2f --- /dev/null +++ b/src/libclient/web-chatview/qwebchannel.js @@ -0,0 +1,427 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Milian Wolff <milian.wolff@kdab.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebChannel module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +"use strict"; + +var QWebChannelMessageTypes = { + signal: 1, + propertyUpdate: 2, + init: 3, + idle: 4, + debug: 5, + invokeMethod: 6, + connectToSignal: 7, + disconnectFromSignal: 8, + setProperty: 9, + response: 10, +}; + +var QWebChannel = function(transport, initCallback) +{ + if (typeof transport !== "object" || typeof transport.send !== "function") { + console.error("The QWebChannel expects a transport object with a send function and onmessage callback property." + + " Given is: transport: " + typeof(transport) + ", transport.send: " + typeof(transport.send)); + return; + } + + var channel = this; + this.transport = transport; + + this.send = function(data) + { + if (typeof(data) !== "string") { + data = JSON.stringify(data); + } + channel.transport.send(data); + } + + this.transport.onmessage = function(message) + { + var data = message.data; + if (typeof data === "string") { + data = JSON.parse(data); + } + switch (data.type) { + case QWebChannelMessageTypes.signal: + channel.handleSignal(data); + break; + case QWebChannelMessageTypes.response: + channel.handleResponse(data); + break; + case QWebChannelMessageTypes.propertyUpdate: + channel.handlePropertyUpdate(data); + break; + default: + console.error("invalid message received:", message.data); + break; + } + } + + this.execCallbacks = {}; + this.execId = 0; + this.exec = function(data, callback) + { + if (!callback) { + // if no callback is given, send directly + channel.send(data); + return; + } + if (channel.execId === Number.MAX_VALUE) { + // wrap + channel.execId = Number.MIN_VALUE; + } + if (data.hasOwnProperty("id")) { + console.error("Cannot exec message with property id: " + JSON.stringify(data)); + return; + } + data.id = channel.execId++; + channel.execCallbacks[data.id] = callback; + channel.send(data); + }; + + this.objects = {}; + + this.handleSignal = function(message) + { + var object = channel.objects[message.object]; + if (object) { + object.signalEmitted(message.signal, message.args); + } else { + console.warn("Unhandled signal: " + message.object + "::" + message.signal); + } + } + + this.handleResponse = function(message) + { + if (!message.hasOwnProperty("id")) { + console.error("Invalid response message received: ", JSON.stringify(message)); + return; + } + channel.execCallbacks[message.id](message.data); + delete channel.execCallbacks[message.id]; + } + + this.handlePropertyUpdate = function(message) + { + for (var i in message.data) { + var data = message.data[i]; + var object = channel.objects[data.object]; + if (object) { + object.propertyUpdate(data.signals, data.properties); + } else { + console.warn("Unhandled property update: " + data.object + "::" + data.signal); + } + } + channel.exec({type: QWebChannelMessageTypes.idle}); + } + + this.debug = function(message) + { + channel.send({type: QWebChannelMessageTypes.debug, data: message}); + }; + + channel.exec({type: QWebChannelMessageTypes.init}, function(data) { + for (var objectName in data) { + var object = new QObject(objectName, data[objectName], channel); + } + // now unwrap properties, which might reference other registered objects + for (var objectName in channel.objects) { + channel.objects[objectName].unwrapProperties(); + } + if (initCallback) { + initCallback(channel); + } + channel.exec({type: QWebChannelMessageTypes.idle}); + }); +}; + +function QObject(name, data, webChannel) +{ + this.__id__ = name; + webChannel.objects[name] = this; + + // List of callbacks that get invoked upon signal emission + this.__objectSignals__ = {}; + + // Cache of all properties, updated when a notify signal is emitted + this.__propertyCache__ = {}; + + var object = this; + + // ---------------------------------------------------------------------- + + this.unwrapQObject = function(response) + { + if (response instanceof Array) { + // support list of objects + var ret = new Array(response.length); + for (var i = 0; i < response.length; ++i) { + ret[i] = object.unwrapQObject(response[i]); + } + return ret; + } + if (!response + || !response["__QObject*__"] + || response.id === undefined) { + return response; + } + + var objectId = response.id; + if (webChannel.objects[objectId]) + return webChannel.objects[objectId]; + + if (!response.data) { + console.error("Cannot unwrap unknown QObject " + objectId + " without data."); + return; + } + + var qObject = new QObject( objectId, response.data, webChannel ); + qObject.destroyed.connect(function() { + if (webChannel.objects[objectId] === qObject) { + delete webChannel.objects[objectId]; + // reset the now deleted QObject to an empty {} object + // just assigning {} though would not have the desired effect, but the + // below also ensures all external references will see the empty map + // NOTE: this detour is necessary to workaround QTBUG-40021 + var propertyNames = []; + for (var propertyName in qObject) { + propertyNames.push(propertyName); + } + for (var idx in propertyNames) { + delete qObject[propertyNames[idx]]; + } + } + }); + // here we are already initialized, and thus must directly unwrap the properties + qObject.unwrapProperties(); + return qObject; + } + + this.unwrapProperties = function() + { + for (var propertyIdx in object.__propertyCache__) { + object.__propertyCache__[propertyIdx] = object.unwrapQObject(object.__propertyCache__[propertyIdx]); + } + } + + function addSignal(signalData, isPropertyNotifySignal) + { + var signalName = signalData[0]; + var signalIndex = signalData[1]; + object[signalName] = { + connect: function(callback) { + if (typeof(callback) !== "function") { + console.error("Bad callback given to connect to signal " + signalName); + return; + } + + object.__objectSignals__[signalIndex] = object.__objectSignals__[signalIndex] || []; + object.__objectSignals__[signalIndex].push(callback); + + if (!isPropertyNotifySignal && signalName !== "destroyed") { + // only required for "pure" signals, handled separately for properties in propertyUpdate + // also note that we always get notified about the destroyed signal + webChannel.exec({ + type: QWebChannelMessageTypes.connectToSignal, + object: object.__id__, + signal: signalIndex + }); + } + }, + disconnect: function(callback) { + if (typeof(callback) !== "function") { + console.error("Bad callback given to disconnect from signal " + signalName); + return; + } + object.__objectSignals__[signalIndex] = object.__objectSignals__[signalIndex] || []; + var idx = object.__objectSignals__[signalIndex].indexOf(callback); + if (idx === -1) { + console.error("Cannot find connection of signal " + signalName + " to " + callback.name); + return; + } + object.__objectSignals__[signalIndex].splice(idx, 1); + if (!isPropertyNotifySignal && object.__objectSignals__[signalIndex].length === 0) { + // only required for "pure" signals, handled separately for properties in propertyUpdate + webChannel.exec({ + type: QWebChannelMessageTypes.disconnectFromSignal, + object: object.__id__, + signal: signalIndex + }); + } + } + }; + } + + /** + * Invokes all callbacks for the given signalname. Also works for property notify callbacks. + */ + function invokeSignalCallbacks(signalName, signalArgs) + { + var connections = object.__objectSignals__[signalName]; + if (connections) { + connections.forEach(function(callback) { + callback.apply(callback, signalArgs); + }); + } + } + + this.propertyUpdate = function(signals, propertyMap) + { + // update property cache + for (var propertyIndex in propertyMap) { + var propertyValue = propertyMap[propertyIndex]; + object.__propertyCache__[propertyIndex] = propertyValue; + } + + for (var signalName in signals) { + // Invoke all callbacks, as signalEmitted() does not. This ensures the + // property cache is updated before the callbacks are invoked. + invokeSignalCallbacks(signalName, signals[signalName]); + } + } + + this.signalEmitted = function(signalName, signalArgs) + { + invokeSignalCallbacks(signalName, this.unwrapQObject(signalArgs)); + } + + function addMethod(methodData) + { + var methodName = methodData[0]; + var methodIdx = methodData[1]; + object[methodName] = function() { + var args = []; + var callback; + for (var i = 0; i < arguments.length; ++i) { + var argument = arguments[i]; + if (typeof argument === "function") + callback = argument; + else if (argument instanceof QObject && webChannel.objects[argument.__id__] !== undefined) + args.push({ + "id": argument.__id__ + }); + else + args.push(argument); + } + + webChannel.exec({ + "type": QWebChannelMessageTypes.invokeMethod, + "object": object.__id__, + "method": methodIdx, + "args": args + }, function(response) { + if (response !== undefined) { + var result = object.unwrapQObject(response); + if (callback) { + (callback)(result); + } + } + }); + }; + } + + function bindGetterSetter(propertyInfo) + { + var propertyIndex = propertyInfo[0]; + var propertyName = propertyInfo[1]; + var notifySignalData = propertyInfo[2]; + // initialize property cache with current value + // NOTE: if this is an object, it is not directly unwrapped as it might + // reference other QObject that we do not know yet + object.__propertyCache__[propertyIndex] = propertyInfo[3]; + + if (notifySignalData) { + if (notifySignalData[0] === 1) { + // signal name is optimized away, reconstruct the actual name + notifySignalData[0] = propertyName + "Changed"; + } + addSignal(notifySignalData, true); + } + + Object.defineProperty(object, propertyName, { + configurable: true, + get: function () { + var propertyValue = object.__propertyCache__[propertyIndex]; + if (propertyValue === undefined) { + // This shouldn't happen + console.warn("Undefined value in property cache for property \"" + propertyName + "\" in object " + object.__id__); + } + + return propertyValue; + }, + set: function(value) { + if (value === undefined) { + console.warn("Property setter for " + propertyName + " called with undefined value!"); + return; + } + object.__propertyCache__[propertyIndex] = value; + var valueToSend = value; + if (valueToSend instanceof QObject && webChannel.objects[valueToSend.__id__] !== undefined) + valueToSend = { "id": valueToSend.__id__ }; + webChannel.exec({ + "type": QWebChannelMessageTypes.setProperty, + "object": object.__id__, + "property": propertyIndex, + "value": valueToSend + }); + } + }); + + } + + // ---------------------------------------------------------------------- + + data.methods.forEach(addMethod); + + data.properties.forEach(bindGetterSetter); + + data.signals.forEach(function(signal) { addSignal(signal, false); }); + + for (var name in data.enums) { + object[name] = data.enums[name]; + } +} + +//required for use with nodejs +if (typeof module === 'object') { + module.exports = { + QWebChannel: QWebChannel + }; +} diff --git a/src/libclient/web-chatview/web.gresource.xml b/src/libclient/web-chatview/web.gresource.xml new file mode 100644 index 0000000000000000000000000000000000000000..584b470f4674f8413f6fc9dd1ce1a10ae89250c7 --- /dev/null +++ b/src/libclient/web-chatview/web.gresource.xml @@ -0,0 +1,23 @@ + <?xml version="1.0" encoding="UTF-8"?> + <gresources> + <gresource prefix="/net/jami/JamiGnome"> + <!-- HTML --> + <file>chatview.html</file> + + <!-- JavaScript --> + <file>chatview.js</file> + <file>linkify.js</file> + <file>linkify-string.js</file> + <file>linkify-html.js</file> + <file>jed.js</file> + <file>emoji.js</file> + + <!-- CSS --> + <file>chatview.css</file> + <file>chatview-gnome.css</file> + <file>emoji.css</file> + <file>fa.css</file> + + <!-- Locale --> + </gresource> + </gresources> diff --git a/src/libclient/webresource.qrc b/src/libclient/webresource.qrc new file mode 100644 index 0000000000000000000000000000000000000000..7ba4703061c2515d5f2f831584e21674df7b27a2 --- /dev/null +++ b/src/libclient/webresource.qrc @@ -0,0 +1,15 @@ +<RCC> + <qresource prefix="/"> + <file alias="chatview.css">web-chatview/chatview.css</file> + <file alias="chatview.html">web-chatview/chatview.html</file> + <file alias="emoji.js">web-chatview/emoji.js</file> + <file alias="chatview.js">web-chatview/chatview.js</file> + <file alias="linkify.js">web-chatview/linkify.js</file> + <file alias="linkify-html.js">web-chatview/linkify-html.js</file> + <file alias="linkify-string.js">web-chatview/linkify-string.js</file> + <file alias="previewInfo.js">web-chatview/previewInfo.js</file> + <file alias="qwebchannel.js">web-chatview/qwebchannel.js</file> + <file alias="chatview-qt.css">web-chatview/chatview-qt.css</file> + <file alias="jed.js">web-chatview/jed.js</file> + </qresource> +</RCC> diff --git a/translations/lrc_ar.ts b/translations/lrc_ar.ts new file mode 100644 index 0000000000000000000000000000000000000000..d04f7781b6312fbd1e0dfdb42a205251c3993d9e --- /dev/null +++ b/translations/lrc_ar.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="ar" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>أنا</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>تعليق</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>يتم التكلم</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>خطأ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>الوارد</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>يتّصل</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>يتم الإتصال</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>يتم البØØ«</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>خامل</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>تم الإنتهاء</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>انتهت المهلة</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>نظير مشغول</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>تم إنجاز الإتصال</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>تم تلقي دعوة</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>تم إضاÙØ© جهة إتصال</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 انضم</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>مكالمة خارجة</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>مكالمة واردة</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>مكالمة خارجة Ùائتة</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>مكالمة داخلة Ùائتة</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>تم قبول الدعوة</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>اÙتراضى</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Ùارغ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Ù…Øاولة</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>يرنّ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>تتم Ø¥Øالته</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>قائمة الإنتظار</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>تقدم</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>مواÙÙ‚</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>مقبول</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>خيارات متعددة</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>انتقال بشكل دائم</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>انتقال مؤقت</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>استخدام وكيل</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>خدمة بديلة</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>طلب غير صالØ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>غير Ù…Ø³Ù…ÙˆØ Ø¨Ù‡</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>يرجى الدÙع</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Ù…Øظور</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>لم يتم العثور</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Ù†Ùاذ مدة الطلب</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>مشغول</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>إجراء مكالمة Ùيديو</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>إجراء مكالمة صوتية</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>إضاÙØ© إلى المØادثات</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>رÙع الØظر عن جهة الاتصال</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>إرسال</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>التمرير إلى نهاية المØادثة</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>إرسال ملÙ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>اقبل</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>أرÙض</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Øظر</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>ملاØظة: يمكنك قبول هذه الدعوة بشكل تلقائي عبر إرسال رسالة.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>تم الإلغاء</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>منذ %d أيام</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>منذ %d ساعات</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>منذ %d دقيقة</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>منذ يوم</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>منذ ساعة</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>ÙÙŠ هذه اللØظة</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>إخÙاق</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>ØØ°Ù</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>إعادة المØاولة</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>يتم البØØ«...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_ar_EG.ts b/translations/lrc_ar_EG.ts new file mode 100644 index 0000000000000000000000000000000000000000..d8f584f31922516bcf99e8aba0d861eea0315371 --- /dev/null +++ b/translations/lrc_ar_EG.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="ar_EG" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>أنا</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>تعليق</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>يتم التكلم</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>خطأ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>الوارد</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>يتّصل</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>يتم الإتصال</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>يتم البØØ«</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>خامل</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>تم الإنتهاء</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>انتهت المهلة</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>نظير مشغول</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>تم إنجاز الإتصال</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>تم تلقي دعوة</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>تم إضاÙØ© جهة إتصال</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 انضم</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>مكالمة خارجة</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>مكالمة واردة</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>مكالمة خارجة Ùائتة</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>مكالمة داخلة Ùائتة</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>تم قبول الدعوة</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>اÙتراضي</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Ùارغ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Ù…Øاولة</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>يرنّ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>تتم Ø¥Øالته</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>قائمة الإنتظار</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>تقدم</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>مواÙÙ‚</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>مقبول</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>خيارات متعددة</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>انتقال بشكل دائم</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>انتقال مؤقت</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>استخدام وكيل</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>خدمة بديلة</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>طلب غير صالØ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>غير Ù…Ø³Ù…ÙˆØ Ø¨Ù‡</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>يرجى الدÙع</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Ù…Øظور</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>لم يتم العثور</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Ù†Ùاذ مدة الطلب</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>مشغول</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>إجراء مكالمة Ùيديو</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>إجراء مكالمة صوتية</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>إضاÙØ© إلى المØادثات</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>رÙع الØظر عن جهة الاتصال</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>إرسال</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>التمرير إلى نهاية المØادثة</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>إرسال ملÙ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>اقبل</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>أرÙض</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Øظر</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>ملاØظة: يمكنك قبول هذه الدعوة بشكل تلقائي عبر إرسال رسالة.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>تم الإلغاء</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>منذ %d أيام</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>منذ %d ساعات</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>منذ %d دقيقة</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>منذ يوم</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>منذ ساعة</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>ÙÙŠ هذه اللØظة</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>إخÙاق</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>ØØ°Ù</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>إعادة المØاولة</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>يتم البØØ«...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_az.ts b/translations/lrc_az.ts new file mode 100644 index 0000000000000000000000000000000000000000..658cd9b17b9bf5edb288db51f329360dfbe800d7 --- /dev/null +++ b/translations/lrc_az.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="az" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 qoÅŸuldu</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>defolt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Tamam</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Fayl göndÉ™r</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Ləğv edilib</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_be.ts b/translations/lrc_be.ts new file mode 100644 index 0000000000000000000000000000000000000000..35ccbdec8e3a6a5b486f1e14b8a22c962d8a91ef --- /dev/null +++ b/translations/lrc_be.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="be" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 далучыўÑÑ</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>па змаўчанні</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Добра</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Ðдправіць файл</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>СкаÑавана</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_be@tarask.ts b/translations/lrc_be@tarask.ts new file mode 100644 index 0000000000000000000000000000000000000000..317921134b99294d466dcd955b0a2c0bef2171e6 --- /dev/null +++ b/translations/lrc_be@tarask.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="be@tarask" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 далучыўÑÑ</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>па змаўчанні</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Добра</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Ðдправіць файл</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>СкаÑавана</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_be_BY.ts b/translations/lrc_be_BY.ts new file mode 100644 index 0000000000000000000000000000000000000000..ac155edaa89c6fa99f1e39df0c835a806a1f1414 --- /dev/null +++ b/translations/lrc_be_BY.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="be_BY" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 далучыўÑÑ</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>па змаўчанні</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Добра</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Ðдправіць файл</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>СкаÑавана</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_bg.ts b/translations/lrc_bg.ts new file mode 100644 index 0000000000000000000000000000000000000000..3b66efdc2cc54182af37ef6426f8dc70e359bec4 --- /dev/null +++ b/translations/lrc_bg.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="bg" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Ðз</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Задържане</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Говорене</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>ГРЕШКÐ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>ВходÑщо</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Обаждане</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Свързване</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>ТърÑене</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>КомуникациÑта е уÑтановена</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Поканата е приета</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Контактът е добавен</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 Ñе приÑъедини</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>ИзходÑщо обаждане</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>ВходÑщо обаждане</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>ПропуÑнато изходÑщо обаждане</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>ПропуÑнато входÑщо обаждане</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>по подразбиране</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>ПозвънÑване</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Добре</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Време за изчакване на заÑвката</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Зает</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Скрий чат изгледа</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Започване на видео разговор</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Започване на глаÑов разговор</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Изпращане</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Изпращане на файл</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Приемане</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Отказ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Блокиране</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Отменено</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Изтриване</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>ТърÑене...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_bg_BG.ts b/translations/lrc_bg_BG.ts new file mode 100644 index 0000000000000000000000000000000000000000..693ae4df9dba8c421532a4db4d47161cadb3878b --- /dev/null +++ b/translations/lrc_bg_BG.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="bg_BG" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Ðз</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Задържане</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Говорене</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>ГРЕШКÐ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>ВходÑщо</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Обаждане</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Свързване</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>ТърÑене</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>КомуникациÑта е уÑтановена</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Поканата е приета</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Контактът е добавен</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 Ñе приÑъедини</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>ИзходÑщо обаждане</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>ВходÑщо обаждане</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>ПропуÑнато изходÑщо обаждане</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>ПропуÑнато входÑщо обаждане</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>по подразбиране</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>ПозвънÑване</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Добре</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Време за изчакване на заÑвката</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Зает</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Скрий чат изгледа</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Започване на видео разговор</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Започване на глаÑов разговор</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Изпращане</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Изпращане на файл</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Приемане</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Отказ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Блокиране</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Отменено</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Изтриване</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>ТърÑене...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_bn.ts b/translations/lrc_bn.ts new file mode 100644 index 0000000000000000000000000000000000000000..77e2b313ff68e212da2fe8c7670e70e3d5aad627 --- /dev/null +++ b/translations/lrc_bn.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="bn" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 যà§à¦•à§à¦¤ হয়েছিল</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>ডিফলà§à¦Ÿ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>ঠিক আছে</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>ফাইল পাঠান</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>বাতিল হয়েছে</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_ca.ts b/translations/lrc_ca.ts new file mode 100644 index 0000000000000000000000000000000000000000..fded7108b07e57d15fded57196868852e83e5481 --- /dev/null +++ b/translations/lrc_ca.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="ca" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Jo</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Mantenir</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Parlant</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Entrant</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Connectant</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Buscant</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>S'ha rebut una invitació</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Contacte afegit</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 s'ha unit</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Trucada sortint</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Trucada entrant</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Trucada sortint perduda</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Trucada entrant perduda</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>per defecte</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Trucant</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>D'acord</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Ocupat</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Amaga finestra de xat</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Fes una video trucada</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Fes una trucada de veu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Afegir a les converses</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Desbloca contacte</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Envia</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Envia el fitxer</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Accepta</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Rebutja</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Bloca</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Nota: una interacció crearà un nou contacte</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Nota: pot acceptar automà ticament aquesta invitació enviant un missatge.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Cancel·lada</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>Fa %d dies</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>Fa %d hores</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>Fa %d minuts</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>Fa un dia</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>Fa una hora</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>Ara mateix</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Fallida</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Suprimeix</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Reintentar</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_cs_CZ.ts b/translations/lrc_cs_CZ.ts new file mode 100644 index 0000000000000000000000000000000000000000..00f5a2ecffb3bbaa96d49b97482774e73297afd7 --- /dev/null +++ b/translations/lrc_cs_CZ.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="cs_CZ" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Já</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Pozastavit</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>ProbÃhá hovor</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>CHYBA</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>PÅ™ÃchozÃ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>VolánÃ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>SpojovánÃ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Hledá se</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>NeÄinný</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>DokonÄeno</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>VyprÅ¡enÃ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>ProtÄ›jÅ¡ek zaneprázdnÄ›n</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Spojenà navázáno</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Pozvánà pÅ™ijato</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Kontakt pÅ™idán</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 se pÅ™ipojil(a)</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Odchozà hovor</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>PÅ™Ãchozà hovor</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>NepÅ™ijatý odchozà hovor</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>ZmeÅ¡kaný pÅ™Ãchozà hovor</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Pozvánà pÅ™ijato</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>výchozÃ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Žádný</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Pokus</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>VyzvánÄ›nÃ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>PÅ™esmÄ›rovává se</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>Fronta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>PrůbÄ›h</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>V pořádku</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>PÅ™ijato</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>VÃce voleb</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Trvale pÅ™emÃstÄ›n</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>DoÄasnÄ› pÅ™emÃstÄ›n</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Použità proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Alternativnà služba</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Nesprávný pÅ™Ãkaz</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Neautorizovaný</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Požadována platba</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Zakázáno</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Nenalezen</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Metoda nenà povolena</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>Nenà pÅ™ijatelný</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Požadovaná autentizace proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>ÄŒasový limit pÅ™Ãkazu</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Je pryÄ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Entita pÅ™Ãkazu je pÅ™ÃliÅ¡ velká</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>URI pÅ™Ãkazu je pÅ™ÃliÅ¡ dlouhý</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Typ média nenà podporován</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Plán URI nenà podporován</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Nesprávná pÅ™Ãpona</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Je požadována pÅ™Ãpona</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>ÄŒasovaÄ relace je pÅ™ÃliÅ¡ krátký</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Interval je pÅ™ÃliÅ¡ krátký</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>DoÄasnÄ› nenà k dispozici</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>Hovor/transakce neexistuje</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Detekována smyÄka</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>PÅ™ÃliÅ¡ mnoho skoků</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Adresa nenà úplná</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>Nejasný</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>ZaneprázdnÄ›ný</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>PÅ™Ãkaz ukonÄen</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Nesprávná událost</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>PÅ™Ãkaz aktualizován</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>PÅ™Ãkaz Äeká</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>NerozluÅ¡titelný</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>VnitÅ™nà chyba serveru</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Neimplementováno</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Nesprávná brána</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Služba nenà k dispozici</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>ÄŒasový limit serveru</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Verze nenà podporována</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Zpráva je pÅ™ÃliÅ¡ velká</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>PÅ™edběžná podmÃnka selhala</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>VÅ¡e je zaneprázdnÄ›no</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Hovor odmÃtnut</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>Nikde neexistuje</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>Nikde nenà pÅ™ijatelný</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Skrýt zprávy</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>UskuteÄnit video hovor</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>UskuteÄnit audio hovor</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>PÅ™idat do konverzacÃ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Odblokovat kontakt</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Odeslat</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Posunout se na konec konverzace</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Poslat soubor</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>PÅ™ijmout</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>OdmÃtnout</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Blokovat</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Poznámka: interakce vytvořà nový kontakt.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Poznámka: můžete tuto pozvánku automaticky pÅ™ijmout poslánÃm zprávy</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>ZruÅ¡eno</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>pÅ™ed %d dny</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>pÅ™ed %d hodinami</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>pÅ™ed %d minutami</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>vÄera</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>pÅ™ed hodinou</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>teÄ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>SelhánÃ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Odstranit</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Zkusit znovu</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Hledá se…</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>Neplatné ID</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>Nebylo možné vyhledat…</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Å patné schéma URI</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_da.ts b/translations/lrc_da.ts new file mode 100644 index 0000000000000000000000000000000000000000..0d6314464a075c705f67b45c3e1d69ebf1faebd3 --- /dev/null +++ b/translations/lrc_da.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="da" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Mig</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Parker</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Taler</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>FEJL</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>IndgÃ¥ende</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Ringer op</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Forbinder</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Søger</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Inaktiv</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Afsluttet</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Timeout</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Partner optaget</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Kommunikation etableret</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Invitation modtaget</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Kontakt tilføjet</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 deltager</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>UdgÃ¥ende opkald</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>IndgÃ¥ende opkald</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Ubesvarede udgÃ¥ende opkald</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Ubesvarede indgÃ¥ende opkald</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Invitation accepteret</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>standard</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Ringer</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>OK</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Anmodning fik timeout</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Optaget</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Gem chatvisning</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Tilføj til samtaler</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Send</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Rul til slutning af samtale</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Send fil</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Accepter</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Afvis</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Blokér</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Annulleret</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Slet</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Søger…</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>Ugyldigt ID</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Ugyldigt URI-skema</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_da_DK.ts b/translations/lrc_da_DK.ts new file mode 100644 index 0000000000000000000000000000000000000000..65cfea41618780fc8ad3f2af3b233024db0b9829 --- /dev/null +++ b/translations/lrc_da_DK.ts @@ -0,0 +1,1546 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS language="da_DK" sourcelanguage="en" version="2.0"> +<context> + <name>Account</name> + <message> + <location filename="../src/libclient/account.cpp" line="331"/> + <source>Ready</source> + <extracomment>Account state</extracomment> + <translation>Klar</translation> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="333"/> + <source>Registered</source> + <extracomment>Account state</extracomment> + <translation>Registreret</translation> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="337"/> + <source>Initializing</source> + <extracomment>Account state</extracomment> + <translation>Initialiserer</translation> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="341"/> + <source>Error</source> + <extracomment>Account state</extracomment> + <translation>Fejl</translation> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="345"/> + <source>Network unreachable</source> + <extracomment>Account state</extracomment> + <translation>Netværk utilgængeligt</translation> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="347"/> + <source>Host unreachable</source> + <extracomment>Account state</extracomment> + <translation>Host utilgængelig</translation> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="335"/> + <source>Not registered</source> + <extracomment>Account state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="339"/> + <source>Trying…</source> + <extracomment>Account state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="343"/> + <source>Authentication failed</source> + <extracomment>Account state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="349"/> + <source>STUN configuration error</source> + <extracomment>Account state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="351"/> + <source>STUN server invalid</source> + <extracomment>Account state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="353"/> + <source>Service unavailable</source> + <extracomment>Account state</extracomment> + <translation>Tjeneste ikke tilgængelig</translation> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="355"/> + <source>Unacceptable</source> + <extracomment>Account state</extracomment> + <translation>Uacceptabel</translation> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="357"/> + <source>Invalid</source> + <extracomment>Account state</extracomment> + <translation>Ugyldig</translation> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="359"/> + <source>Request timeout</source> + <extracomment>Account state</extracomment> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>AccountChecksModel</name> + <message> + <location filename="../src/libclient/securityevaluationmodel.cpp" line="438"/> + <source>Configuration</source> + <translation>Konfiguration</translation> + </message> +</context> +<context> + <name>BootstrapModel</name> + <message> + <location filename="../src/libclient/bootstrapmodel.cpp" line="379"/> + <source>Hostname</source> + <translation>Værtsnavn</translation> + </message> + <message> + <location filename="../src/libclient/bootstrapmodel.cpp" line="381"/> + <source>Port</source> + <translation>Port</translation> + </message> +</context> +<context> + <name>Call</name> + <message> + <location filename="../src/libclient/call.cpp" line="720"/> + <source>New</source> + <extracomment>Call state</extracomment> + <translation>Ny</translation> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="723"/> + <source>Ringing</source> + <extracomment>Call state</extracomment> + <translation>Ringer</translation> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="726"/> + <source>Calling</source> + <extracomment>Call state</extracomment> + <translation>Ringer op</translation> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="729"/> + <source>Talking</source> + <extracomment>Call state</extracomment> + <translation>Taler</translation> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="732"/> + <source>Dialing</source> + <extracomment>Call state</extracomment> + <translation>Ringer op</translation> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="735"/> + <source>Hold</source> + <extracomment>Call state</extracomment> + <translation>Parkeret</translation> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="738"/> + <source>Failed</source> + <extracomment>Call state</extracomment> + <translation>Fejlede</translation> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="741"/> + <source>Busy</source> + <extracomment>Call state</extracomment> + <translation>Optaget</translation> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="744"/> + <source>Transfer</source> + <extracomment>Call state</extracomment> + <translation>Overfør</translation> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="747"/> + <source>Transfer hold</source> + <extracomment>Call state</extracomment> + <translation>Parkeret for overførsel</translation> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="750"/> + <source>Over</source> + <extracomment>Call state</extracomment> + <translation>Ovre</translation> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="753"/> + <source>Error</source> + <extracomment>Call state</extracomment> + <translation>Fejl</translation> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="756"/> + <location filename="../src/libclient/call.cpp" line="861"/> + <source>Conference</source> + <extracomment>Call state</extracomment> + <translation>Konference</translation> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="759"/> + <source>Conference (hold)</source> + <extracomment>Call state</extracomment> + <translation>Konference (parkeret)</translation> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="762"/> + <source>ERROR</source> + <extracomment>Call state</extracomment> + <translation>FEJL</translation> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="765"/> + <source>Searching for</source> + <extracomment>Call state</extracomment> + <translation>Søger efter</translation> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="768"/> + <source>Aborted</source> + <extracomment>Call state</extracomment> + <translation>Afbrudt</translation> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="771"/> + <source>Communication established</source> + <extracomment>Call state</extracomment> + <translation>Kommunikation etableret</translation> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="865"/> + <source>Unknown</source> + <translation>Ukendt</translation> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="2237"/> + <source>Account: </source> + <translation>Konto:</translation> + </message> +</context> +<context> + <name>CallModel</name> + <message> + <location filename="../src/libclient/callmodel.cpp" line="924"/> + <source>Calls</source> + <translation>Opkald</translation> + </message> +</context> +<context> + <name>CallModelPrivate</name> + <message> + <location filename="../src/libclient/callmodel.cpp" line="559"/> + <location filename="../src/libclient/callmodel.cpp" line="584"/> + <source>Invalid account</source> + <translation>Ugyldig konto</translation> + </message> +</context> +<context> + <name>CallPrivate</name> + <message> + <location filename="../src/libclient/call.cpp" line="1794"/> + <source>Aborted</source> + <translation>Afbrudt</translation> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="1815"/> + <source>No account registered!</source> + <translation>Ingen konto registreret!</translation> + </message> +</context> +<context> + <name>CategorizedBookmarkModel</name> + <message> + <location filename="../src/libclient/categorizedbookmarkmodel.cpp" line="181"/> + <source>Most popular</source> + <extracomment>Most popular contacts</extracomment> + <translation>Mest populære</translation> + </message> + <message> + <location filename="../src/libclient/categorizedbookmarkmodel.cpp" line="299"/> + <source>Contacts</source> + <translation>Kontakter</translation> + </message> +</context> +<context> + <name>CategorizedContactModel</name> + <message> + <location filename="../src/libclient/categorizedcontactmodel.cpp" line="401"/> + <source>Contacts</source> + <translation>Kontakter</translation> + </message> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="129"/> + <source>Empty</source> + <translation>Tom</translation> + </message> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="135"/> + <location filename="../src/libclient/private/sortproxies.cpp" line="153"/> + <source>Unknown</source> + <translation>Ukendt</translation> + </message> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="141"/> + <source>Never</source> + <translation>Aldrig</translation> + </message> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="147"/> + <source>Other</source> + <translation>Andre</translation> + </message> +</context> +<context> + <name>CategorizedHistoryModel</name> + <message> + <location filename="../src/libclient/categorizedhistorymodel.cpp" line="414"/> + <source>History</source> + <translation>Historik</translation> + </message> +</context> +<context> + <name>ChainOfTrustModel</name> + <message> + <location filename="../src/libclient/chainoftrustmodel.cpp" line="173"/> + <source>Chain of trust</source> + <translation>Troværdighedskæde</translation> + </message> +</context> +<context> + <name>CollectionModel</name> + <message> + <location filename="../src/libclient/collectionmodel.cpp" line="279"/> + <source>Name</source> + <translation>Navn</translation> + </message> +</context> +<context> + <name>ContactSortingCategoryModel</name> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="49"/> + <source>Name</source> + <translation>Navn</translation> + </message> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="50"/> + <source>Organisation</source> + <translation>Organisation</translation> + </message> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="51"/> + <source>Recently used</source> + <translation>Senest brugte</translation> + </message> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="52"/> + <source>Group</source> + <translation>Gruppe</translation> + </message> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="53"/> + <source>Department</source> + <translation>Afdeling</translation> + </message> +</context> +<context> + <name>HistorySortingCategoryModel</name> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="57"/> + <source>Date</source> + <translation>Dato</translation> + </message> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="58"/> + <source>Name</source> + <translation>Navn</translation> + </message> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="59"/> + <source>Popularity</source> + <translation>Popularitet</translation> + </message> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="60"/> + <source>Duration</source> + <translation>Varighed</translation> + </message> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="61"/> + <source>Total time</source> + <translation>Samlet tid</translation> + </message> +</context> +<context> + <name>HistoryTimeCategoryModel</name> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="50"/> + <source>Today</source> + <translation>I dag</translation> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="51"/> + <source>Yesterday</source> + <translation>I gÃ¥r</translation> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="58"/> + <source>Two weeks ago</source> + <translation>For to uger siden</translation> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="59"/> + <source>Three weeks ago</source> + <translation>For tre uger siden</translation> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="57"/> + <source>A week ago</source> + <translation>For en uge siden</translation> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="60"/> + <source>A month ago</source> + <translation>For en mÃ¥ned siden</translation> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="61"/> + <source>Two months ago</source> + <translation>For to mÃ¥neder siden</translation> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="62"/> + <source>Three months ago</source> + <translation>For tre mÃ¥neder siden</translation> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="63"/> + <source>Four months ago</source> + <translation>For fire mÃ¥neder siden</translation> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="64"/> + <source>Five months ago</source> + <translation>For fem mÃ¥neder siden</translation> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="65"/> + <source>Six months ago</source> + <translation>For seks mÃ¥neder siden</translation> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="66"/> + <source>Seven months ago</source> + <translation>For syv mÃ¥neder siden</translation> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="67"/> + <source>Eight months ago</source> + <translation>For otte mÃ¥neder siden</translation> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="68"/> + <source>Nine months ago</source> + <translation>For ni mÃ¥neder siden</translation> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="69"/> + <source>Ten months ago</source> + <translation>For ti mÃ¥neder siden</translation> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="70"/> + <source>Eleven months ago</source> + <translation>For elleve mÃ¥neder siden</translation> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="71"/> + <source>Twelve months ago</source> + <translation>For tolv mÃ¥neder siden</translation> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="72"/> + <source>A year ago</source> + <translation>For et Ã¥r siden</translation> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="73"/> + <source>Very long time ago</source> + <translation>For meget lang tid siden</translation> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="74"/> + <source>Never</source> + <translation>Aldrig</translation> + </message> +</context> +<context> + <name>InstantMessagingModel</name> + <message> + <location filename="../src/libclient/media/textrecording.cpp" line="816"/> + <source>Me</source> + <translation>Mig</translation> + </message> +</context> +<context> + <name>MacroModel</name> + <message> + <location filename="../src/libclient/macromodel.cpp" line="157"/> + <source>Macros</source> + <translation>Makroer</translation> + </message> + <message> + <location filename="../src/libclient/macromodel.cpp" line="263"/> + <source>New</source> + <translation>Ny</translation> + </message> + <message> + <location filename="../src/libclient/macromodel.cpp" line="264"/> + <source>Other</source> + <translation>Andre</translation> + </message> +</context> +<context> + <name>MacroModelPrivate</name> + <message> + <location filename="../src/libclient/macromodel.cpp" line="77"/> + <source>Other</source> + <translation>Andre</translation> + </message> +</context> +<context> + <name>NumberCategoryModel</name> + <message> + <location filename="../src/libclient/numbercategorymodel.cpp" line="56"/> + <source>Uncategorized</source> + <translation>Ukategoriseret</translation> + </message> +</context> +<context> + <name>NumberCompletionModel</name> + <message> + <location filename="../src/libclient/numbercompletionmodel.cpp" line="265"/> + <source>URI</source> + <translation>URI</translation> + </message> + <message> + <location filename="../src/libclient/numbercompletionmodel.cpp" line="265"/> + <source>Name</source> + <translation>Navn</translation> + </message> + <message> + <location filename="../src/libclient/numbercompletionmodel.cpp" line="265"/> + <source>Account</source> + <translation>Konto</translation> + </message> + <message> + <location filename="../src/libclient/numbercompletionmodel.cpp" line="265"/> + <source>Weight</source> + <translation>Vægt</translation> + </message> +</context> +<context> + <name>PersonModel</name> + <message> + <location filename="../src/libclient/personmodel.cpp" line="171"/> + <source>Persons</source> + <translation>Personer</translation> + </message> +</context> +<context> + <name>PhoneDirectoryModel</name> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="234"/> + <source>This account does not support presence tracking</source> + <translation>Denne konto understøtter ikke statussporing</translation> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="237"/> + <source>No associated account</source> + <translation>Ingen tilknyttet konto</translation> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="305"/> + <source>URI</source> + <translation>URI</translation> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="305"/> + <source>Type</source> + <translation>Type</translation> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="305"/> + <source>Person</source> + <translation>Person</translation> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="305"/> + <source>Account</source> + <translation>Konto</translation> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="305"/> + <source>State</source> + <translation>Tilstand</translation> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="305"/> + <source>Call count</source> + <translation>Antal opkald</translation> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="305"/> + <source>Week count</source> + <translation>Antal seneste uge</translation> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="306"/> + <source>Trimester count</source> + <translation>Antal seneste kvartal</translation> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="306"/> + <source>Have Called</source> + <translation>Har ringet</translation> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="306"/> + <source>Last used</source> + <translation>Sidst brugt</translation> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="306"/> + <source>Name_count</source> + <translation>Navn_antal</translation> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="306"/> + <source>Total (in seconds)</source> + <translation>Samlet (i sekunder)</translation> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="306"/> + <source>Popularity_index</source> + <translation>Popularitetsindex</translation> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="307"/> + <source>Bookmarked</source> + <translation>Bogmærket</translation> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="307"/> + <source>Tracked</source> + <translation>Sporet</translation> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="307"/> + <source>Present</source> + <translation>Tilstede</translation> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="307"/> + <source>Presence message</source> + <translation>Statusbesked</translation> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="307"/> + <source>UID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="307"/> + <source>Has certificate</source> + <translation>Har certifikat</translation> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="307"/> + <source>Registered name</source> + <translation>Registreret navn</translation> + </message> +</context> +<context> + <name>PresenceStatusModel</name> + <message> + <location filename="../src/libclient/presencestatusmodel.cpp" line="197"/> + <source>Name</source> + <translation>Navn</translation> + </message> + <message> + <location filename="../src/libclient/presencestatusmodel.cpp" line="197"/> + <source>Message</source> + <translation>Besked</translation> + </message> + <message> + <location filename="../src/libclient/presencestatusmodel.cpp" line="197"/> + <source>Color</source> + <translation>Farve</translation> + </message> + <message> + <location filename="../src/libclient/presencestatusmodel.cpp" line="197"/> + <source>Present</source> + <translation>Tilstede</translation> + </message> + <message> + <location filename="../src/libclient/presencestatusmodel.cpp" line="197"/> + <source>Default</source> + <translation>Standard</translation> + </message> + <message> + <location filename="../src/libclient/presencestatusmodel.cpp" line="308"/> + <location filename="../src/libclient/presencestatusmodel.cpp" line="361"/> + <source>Custom</source> + <translation>Brugerdefineret</translation> + </message> + <message> + <location filename="../src/libclient/presencestatusmodel.cpp" line="308"/> + <location filename="../src/libclient/presencestatusmodel.cpp" line="310"/> + <location filename="../src/libclient/presencestatusmodel.cpp" line="354"/> + <location filename="../src/libclient/presencestatusmodel.cpp" line="361"/> + <source>N/A</source> + <translation>N/A</translation> + </message> +</context> +<context> + <name>ProfileModel</name> + <message> + <location filename="../src/libclient/profilemodel.cpp" line="637"/> + <source>Profiles</source> + <translation>Profiler</translation> + </message> +</context> +<context> + <name>ProfileModelPrivate</name> + <message> + <location filename="../src/libclient/profilemodel.cpp" line="751"/> + <source>New profile</source> + <translation>Ny profil</translation> + </message> +</context> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/accountstatusmodel.cpp" line="177"/> + <source>Message</source> + <translation>Besked</translation> + </message> + <message> + <location filename="../src/libclient/accountstatusmodel.cpp" line="179"/> + <source>Code</source> + <translation>Kode</translation> + </message> + <message> + <location filename="../src/libclient/accountstatusmodel.cpp" line="181"/> + <source>Time</source> + <translation>Tid</translation> + </message> + <message> + <location filename="../src/libclient/accountstatusmodel.cpp" line="183"/> + <source>Counter</source> + <translation>Tæller</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="42"/> + <source>Has a private key</source> + <translation>Har en privat nøgle</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="43"/> + <source>Is not expired</source> + <translation>Er ikke udløbet</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="44"/> + <source>Has strong signing</source> + <translation>Har stærk signering</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="45"/> + <source>Is not self signed</source> + <translation>Er ikke selvsigneret</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="46"/> + <source>Have a matching key pair</source> + <translation>Har et tilsvarende nøglepar</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="47"/> + <source>Has the right private key file permissions</source> + <translation>Har de rigtige tilladelser for den private nøglefil</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="48"/> + <source>Has the right public key file permissions</source> + <translation>Har de rigtige tilladelser for den offentlige nøglefil</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="49"/> + <source>Has the right private key directory permissions</source> + <translation>Har de rigtige tilladelser for den private nøglemappe</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="50"/> + <source>Has the right public key directory permissions</source> + <translation>Har de rigtige tilladelser for den offentlige nøglemappe</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="51"/> + <source>Has the right private key directory location</source> + <translation>Har den rigtige placering af mappe til den private nøgle</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="52"/> + <source>Has the right public key directory location</source> + <translation>Har den rigtige placering af mappe til den offentlige nøgle</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="53"/> + <source>Has the right private key SELinux attributes</source> + <translation>Har de rigtige SELinux-attributter til den private nøgle</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="54"/> + <source>Has the right public key SELinux attributes</source> + <translation>Har de rigtige SELinux-attributter til den offentlige nøgle</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="55"/> + <source>The certificate file exist and is readable</source> + <translation>Certifikatfilen findes og er læsbar</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="56"/> + <source>The file is a valid certificate</source> + <translation>Filen er et gyldigt certifikat</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="57"/> + <source>The certificate has a valid authority</source> + <translation>Certifikatet har en gyldig autoritet</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="58"/> + <source>The certificate has a known authority</source> + <translation>Certifikatet har en kendt autoritet</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="59"/> + <source>The certificate is not revoked</source> + <translation>Certifikatet er ikke tilbagekaldt</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="60"/> + <source>The certificate authority match</source> + <translation>Certikatets autoritet passer</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="61"/> + <source>The certificate has the expected owner</source> + <translation>Certifikatet har den forventede ejer</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="62"/> + <source>The certificate is within its active period</source> + <translation>Certifikatet er i dets aktive periode</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="90"/> + <source>Expiration date</source> + <translation>Udløbsdato</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="91"/> + <source>Activation date</source> + <translation>Aktiveringsdato</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="92"/> + <source>Require a private key password</source> + <translation>Benyt en adgangskode til den private nøgle</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="93"/> + <source>Public signature</source> + <translation>Offentlig signatur</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="94"/> + <source>Version</source> + <translation>Version</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="95"/> + <source>Serial number</source> + <translation>Serienummer</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="96"/> + <source>Issuer</source> + <translation>Udsteder</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="97"/> + <source>Subject key algorithm</source> + <translation>Subject key-algoritme</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="98"/> + <source>Common name (CN)</source> + <translation>Fællesnavn (CN)</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="99"/> + <source>Name (N)</source> + <translation>Navn (N)</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="100"/> + <source>Organization (O)</source> + <translation>Organisation (O)</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="101"/> + <source>Signature algorithm</source> + <translation>Signaturalgoritme</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="102"/> + <source>Md5 fingerprint</source> + <translation>MD5-fingeraftryk</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="103"/> + <source>Sha1 fingerprint</source> + <translation>SHA1-fingeraftryk</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="104"/> + <source>Public key ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="105"/> + <source>Issuer domain name</source> + <translation>Udsteders domænenavn</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="106"/> + <source>Next expected update</source> + <translation>Næste forventede opdatering</translation> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="107"/> + <source>Outgoing server</source> + <translation>UdgÃ¥ende server</translation> + </message> + <message> + <location filename="../src/libclient/certificatemodel.cpp" line="183"/> + <source>Local certificate store</source> + <translation>Lokalt certifikatlager</translation> + </message> + <message> + <location filename="../src/libclient/certificatemodel.cpp" line="267"/> + <location filename="../src/libclient/localprofilecollection.cpp" line="220"/> + <source>Default</source> + <translation>Standard</translation> + </message> + <message> + <location filename="../src/libclient/certificatemodel.cpp" line="267"/> + <source>Certificate not associated with a group</source> + <translation>Certikat ikke tilknyttet en gruppe</translation> + </message> + <message> + <location filename="../src/libclient/certificatemodel.cpp" line="397"/> + <source>A certificate</source> + <translation>Et certifikat</translation> + </message> + <message> + <location filename="../src/libclient/certificatemodel.cpp" line="397"/> + <source>An organisation</source> + <translation>En organisation</translation> + </message> + <message> + <location filename="../src/libclient/certificatemodel.cpp" line="420"/> + <source>Details</source> + <translation>Detaljer</translation> + </message> + <message> + <location filename="../src/libclient/certificatemodel.cpp" line="420"/> + <source>The content of the certificate</source> + <translation>Certifikatets indhold</translation> + </message> + <message> + <location filename="../src/libclient/certificatemodel.cpp" line="421"/> + <source>Checks</source> + <translation>Afkrydsninger</translation> + </message> + <message> + <location filename="../src/libclient/certificatemodel.cpp" line="421"/> + <source>Various security related information</source> + <translation>Diverse sikkerhedsrelateret information</translation> + </message> + <message> + <location filename="../src/libclient/certificatemodel.cpp" line="610"/> + <source>Header</source> + <translation>Hoved</translation> + </message> + <message> + <location filename="../src/libclient/daemoncertificatecollection.cpp" line="148"/> + <source>Daemon certificate store</source> + <translation>Baggrundscertifikatslager</translation> + </message> + <message> + <location filename="../src/libclient/daemoncertificatecollection.cpp" line="152"/> + <source>%1 banned list</source> + <extracomment>The list of banned certificates for this account</extracomment> + <translation>%1 blokerings-liste</translation> + </message> + <message> + <location filename="../src/libclient/daemoncertificatecollection.cpp" line="155"/> + <source>%1 allowed list</source> + <extracomment>The list of allowed certificates for this account</extracomment> + <translation>%1 tilladelses-liste</translation> + </message> + <message> + <location filename="../src/libclient/daemoncertificatecollection.cpp" line="160"/> + <location filename="../src/libclient/foldercertificatecollection.cpp" line="198"/> + <source>Certificate</source> + <translation>Certifikat</translation> + </message> + <message> + <location filename="../src/libclient/extensions/presencecollectionextension.cpp" line="38"/> + <source>Presence tracking</source> + <translation>Statussporing</translation> + </message> + <message> + <location filename="../src/libclient/extensions/securityevaluationextension.cpp" line="63"/> + <source>Security evaluation</source> + <translation>SIkkerhedsbedømmelse</translation> + </message> + <message> + <location filename="../src/libclient/fallbackpersoncollection.cpp" line="194"/> + <location filename="../src/libclient/transitionalpersonbackend.cpp" line="150"/> + <source>Contact</source> + <translation>Kontakt</translation> + </message> + <message> + <location filename="../src/libclient/localbookmarkcollection.cpp" line="212"/> + <source>Local bookmarks</source> + <translation>Lokale bogmærker</translation> + </message> + <message> + <location filename="../src/libclient/localbookmarkcollection.cpp" line="217"/> + <location filename="../src/libclient/useractionmodel.cpp" line="532"/> + <source>Bookmark</source> + <translation>Bogmærke</translation> + </message> + <message> + <location filename="../src/libclient/localhistorycollection.cpp" line="195"/> + <source>Local history</source> + <translation>Lokalhistorik</translation> + </message> + <message> + <location filename="../src/libclient/localhistorycollection.cpp" line="200"/> + <source>History</source> + <translation>Historik</translation> + </message> + <message> + <location filename="../src/libclient/localmacrocollection.cpp" line="190"/> + <source>Local macros</source> + <translation>Lokale makroer</translation> + </message> + <message> + <location filename="../src/libclient/localmacrocollection.cpp" line="195"/> + <source>Macro</source> + <translation>Makro</translation> + </message> + <message> + <location filename="../src/libclient/localrecordingcollection.cpp" line="101"/> + <source>Local recordings</source> + <translation>Lokale optagelser</translation> + </message> + <message> + <location filename="../src/libclient/localrecordingcollection.cpp" line="106"/> + <location filename="../src/libclient/localtextrecordingcollection.cpp" line="170"/> + <source>Recording</source> + <translation>Optagelse</translation> + </message> + <message> + <location filename="../src/libclient/localringtonecollection.cpp" line="220"/> + <source>Local ringtones</source> + <translation>Lokale ringetoner</translation> + </message> + <message> + <location filename="../src/libclient/localringtonecollection.cpp" line="225"/> + <source>Ringtone</source> + <translation>Ringetone</translation> + </message> + <message> + <location filename="../src/libclient/localtextrecordingcollection.cpp" line="165"/> + <source>Local text recordings</source> + <translation>Lokale tekstoptagelser</translation> + </message> + <message> + <location filename="../src/libclient/numbercategory.cpp" line="72"/> + <source>Phone number types</source> + <translation>Telefonnummertyper</translation> + </message> + <message> + <location filename="../src/libclient/numbercategorymodel.cpp" line="186"/> + <source>Other</source> + <translation>Andre</translation> + </message> + <message> + <location filename="../src/libclient/protocolmodel.cpp" line="50"/> + <source>Ring Account</source> + <translation>Ring-konto</translation> + </message> + <message> + <location filename="../src/libclient/protocolmodel.cpp" line="51"/> + <source>SIP Account</source> + <translation>SIP-konto</translation> + </message> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="315"/> + <source>Me</source> + <translation>Mig</translation> + </message> + <message> + <location filename="../src/libclient/securityevaluationmodel.cpp" line="38"/> + <source>TLS is disabled, the negotiation won't be encrypted. Your communication will be vulnerable to snooping</source> + <translation>TLS er deaktiveret, protokol-forhandlingen vil ikke være krypteret. Din kommunikation er sÃ¥rbar overfor aflytning.</translation> + </message> + <message> + <location filename="../src/libclient/securityevaluationmodel.cpp" line="40"/> + <source>Your certificate and authority don't match, if your certificate require an authority, it won't work</source> + <translation>Dit certifikat og autoritet stemmer ikke overens. Hvis dit certifikat kræver en autoritet vil det ikke virke</translation> + </message> + <message> + <location filename="../src/libclient/securityevaluationmodel.cpp" line="41"/> + <source>The outgoing server specified doesn't match the hostname or the one included in the certificate</source> + <translation>Den angivne udgÃ¥ende server passer ikke med værtsnavnet eller det i certifikatet inkluderede</translation> + </message> + <message> + <location filename="../src/libclient/securityevaluationmodel.cpp" line="42"/> + <source>The "verify incoming certificate" option is disabled, this leave you vulnerable to man in the middle attack</source> + <translation>Valgmuligheden "bekræft indgÃ¥ende certikat" er deaktiveret, dette gør dig sÃ¥rbar over for "man in the middle"-angreb</translation> + </message> + <message> + <location filename="../src/libclient/securityevaluationmodel.cpp" line="43"/> + <source>The "verify answer certificate" option is disabled, this leave you vulnerable to man in the middle attack</source> + <translation>Valgmuligheden "bekræft svarcertikat" er deaktiveret, dette gør dig sÃ¥rbar over for "man in the middle"-angreb</translation> + </message> + <message> + <location filename="../src/libclient/securityevaluationmodel.cpp" line="44"/> + <source>None of your certificate provide a private key, this is required. Please select a private key or use a certificate with one built-in</source> + <translation>Ingen af dine certifikater tilbyder en privat nøgle, dette er krævet. Vælg venligst en privat nøgle eller brug et certifikat med en indbygget</translation> + </message> + <message> + <location filename="../src/libclient/securityevaluationmodel.cpp" line="47"/> + <source>No certificate authority is provided, it won't be possible to validate if the answer certificates are valid. Some account may also not work.</source> + <translation>Ingen certifikatautoritet er tilgængelig, det vil ikke være muligt at validere om svarcertifikatet er gyldigt. Nogle konti vil mÃ¥ske heller ikke virke.</translation> + </message> + <message> + <location filename="../src/libclient/securityevaluationmodel.cpp" line="46"/> + <source>No certificate has been provided. This is, for now, unsupported by Ring</source> + <translation>Intet certifikat er tilgængeligt. Dette er, for øjeblikket, ikke understøttet af Ring</translation> + </message> + <message> + <location filename="../src/libclient/securityevaluationmodel.cpp" line="37"/> + <source>Your media streams are not encrypted, please enable SDES</source> + <translation>Dine media streams er ikke krypteret, venligst aktiver SDES</translation> + </message> + <message> + <location filename="../src/libclient/securityevaluationmodel.cpp" line="50"/> + <source>Your certificate is expired, please contact your system administrator.</source> + <translation>Dit certifikat er udløbet, kontakt venligst din systemadministrator</translation> + </message> + <message> + <location filename="../src/libclient/securityevaluationmodel.cpp" line="51"/> + <source>Your certificate is self signed. This break the chain of trust.</source> + <translation>Dit certifikat er selvsigneret. Dette bryder troværdighedskæden.</translation> + </message> + <message> + <location filename="../src/libclient/tlsmethodmodel.cpp" line="64"/> + <source>Default</source> + <comment>Default TLS protocol version</comment> + <translation>Standard</translation> + </message> + <message> + <location filename="../src/libclient/transitionalpersonbackend.cpp" line="145"/> + <source>Contact placeholders</source> + <translation>Kontaktstedfortræder</translation> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="517"/> + <location filename="../src/libclient/useractionmodel.cpp" line="759"/> + <source>Accept</source> + <translation>Accepter</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="60"/> + <location filename="../src/libclient/useractionmodel.cpp" line="518"/> + <location filename="../src/libclient/useractionmodel.cpp" line="771"/> + <source>Hold</source> + <translation>Parker</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="62"/> + <source>Talking</source> + <translation>Taler</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="64"/> + <source>ERROR</source> + <translation>FEJL</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="66"/> + <source>Incoming</source> + <translation>IndgÃ¥ende</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="68"/> + <source>Calling</source> + <translation>Ringer op</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="70"/> + <source>Connecting</source> + <translation>Forbinder</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="72"/> + <source>Searching</source> + <translation>Søger</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="74"/> + <source>Inactive</source> + <translation>Inaktiv</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="76"/> + <location filename="../src/libclient/api/call.h" line="82"/> + <source>Finished</source> + <translation>Afsluttet</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="78"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="80"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="84"/> + <source>Communication established</source> + <translation>Kommunikation etableret</translation> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="519"/> + <source>Mute audio</source> + <translation>Mute lyd</translation> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="520"/> + <source>Mute video</source> + <translation>Mute video</translation> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="521"/> + <source>Server transfer</source> + <translation>Serveroverførsel</translation> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="522"/> + <source>Record</source> + <translation>Optag</translation> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="523"/> + <location filename="../src/libclient/useractionmodel.cpp" line="789"/> + <source>Hangup</source> + <translation>Læg pÃ¥</translation> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="524"/> + <source>Join</source> + <translation>Deltag</translation> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="525"/> + <source>Add new</source> + <translation>Tilføj ny</translation> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="526"/> + <source>Toggle video</source> + <translation>Video til/fra</translation> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="527"/> + <source>Add a contact</source> + <translation>Tilføj en kontakt</translation> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="528"/> + <source>Add to existing contact</source> + <translation>Tilføj til eksisterende kontakt</translation> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="529"/> + <source>Delete contact</source> + <translation>Slet kontakt</translation> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="530"/> + <source>Email contact</source> + <translation>E-mail til kontakt</translation> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="531"/> + <source>Copy contact</source> + <translation>Kopiér kontakt</translation> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="534"/> + <source>Add phone number</source> + <translation>Tilføj telefonnummer</translation> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="535"/> + <source>Call again</source> + <translation>Ring op igen</translation> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="536"/> + <source>Edit contact details</source> + <translation>Rediger kontakt-detaljer</translation> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="537"/> + <source>Remove from history</source> + <translation>Fjern fra historik</translation> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="786"/> + <source>Remove</source> + <translation>Fjern</translation> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="756"/> + <source>Call</source> + <translation>Ring op</translation> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="533"/> + <source>Open chat</source> + <translation>Ã…bn chat</translation> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="768"/> + <source>Unhold</source> + <translation>Uparker</translation> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="779"/> + <source>Cancel</source> + <translation>Annuller</translation> + </message> + <message> + <location filename="../src/libclient/localprofilecollection.cpp" line="147"/> + <source>Local profiles</source> + <translation>Lokale profiler</translation> + </message> + <message> + <location filename="../src/libclient/localprofilecollection.cpp" line="152"/> + <source>Profile Collection</source> + <translation>Profil-samling</translation> + </message> + <message> + <location filename="../src/libclient/peerprofilecollection.cpp" line="141"/> + <source>Peer profiles</source> + <translation>Partners profiler</translation> + </message> + <message> + <location filename="../src/libclient/peerprofilecollection.cpp" line="146"/> + <source>Peers Profiles Collection</source> + <translation>Partners Profil-samling</translation> + </message> + <message> + <location filename="../src/libclient/conversationmodel.cpp" line="1267"/> + <location filename="../src/libclient/conversationmodel.cpp" line="1633"/> + <location filename="../src/libclient/conversationmodel.cpp" line="1885"/> + <source>Invitation received</source> + <translation>Invitation modtaget</translation> + </message> + <message> + <location filename="../src/libclient/conversationmodel.cpp" line="1268"/> + <source>Contact added</source> + <translation>Kontakt tilføjet</translation> + </message> + <message> + <location filename="../src/libclient/conversationmodel.cpp" line="1303"/> + <location filename="../src/libclient/conversationmodel.cpp" line="1310"/> + <source>Invitation accepted</source> + <translation>Invitation accepteret</translation> + </message> + <message> + <location filename="../src/libclient/conversationmodel.cpp" line="1519"/> + <source>📞 Outgoing call</source> + <translation>📞 UdgÃ¥ende opkald</translation> + </message> + <message> + <location filename="../src/libclient/conversationmodel.cpp" line="1521"/> + <source>📞 Incoming call</source> + <translation>📞 IndgÃ¥ende opkald</translation> + </message> + <message> + <location filename="../src/libclient/conversationmodel.cpp" line="1534"/> + <source>📞 Outgoing call - </source> + <translation>📞 UdgÃ¥ende opkald - </translation> + </message> + <message> + <location filename="../src/libclient/conversationmodel.cpp" line="1537"/> + <source>📞 Incoming call - </source> + <translation>📞 IndgÃ¥ende opkald - </translation> + </message> + <message> + <location filename="../src/libclient/conversationmodel.cpp" line="1541"/> + <source>🕽 Missed outgoing call</source> + <translation>🕽 Mistede udgÃ¥ende opkald</translation> + </message> + <message> + <location filename="../src/libclient/conversationmodel.cpp" line="1543"/> + <source>🕽 Missed incoming call</source> + <translation>🕽 Misteede indgÃ¥ende opkald</translation> + </message> +</context> +<context> + <name>RecentModel</name> + <message> + <location filename="../src/libclient/recentmodel.cpp" line="614"/> + <source>Recent persons</source> + <translation>Seneste personer</translation> + </message> +</context> +<context> + <name>RingDeviceModel</name> + <message> + <location filename="../src/libclient/ringdevicemodel.cpp" line="110"/> + <source>ID</source> + <translation>ID</translation> + </message> + <message> + <location filename="../src/libclient/ringdevicemodel.cpp" line="112"/> + <source>Name</source> + <translation>Navn</translation> + </message> +</context> +<context> + <name>SecurityEvaluationModelPrivate</name> + <message> + <location filename="../src/libclient/securityevaluationmodel.cpp" line="683"/> + <source>Authority</source> + <translation>Autoritet</translation> + </message> +</context> +<context> + <name>TlsMethodModel</name> + <message> + <location filename="../src/libclient/tlsmethodmodel.cpp" line="101"/> + <source>Automatic</source> + <translation>Automatisk</translation> + </message> +</context> +<context> + <name>Video::SourceModel</name> + <message> + <location filename="../src/libclient/video/sourcemodel.cpp" line="95"/> + <source>NONE</source> + <translation>NONE</translation> + </message> + <message> + <location filename="../src/libclient/video/sourcemodel.cpp" line="101"/> + <source>SCREEN</source> + <translation>SCREEN</translation> + </message> + <message> + <location filename="../src/libclient/video/sourcemodel.cpp" line="107"/> + <source>FILE</source> + <translation>FILE</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="392"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="723"/> + <source>Invalid ringID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="726"/> + <source>Not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="729"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="363"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>media::RecordingModel</name> + <message> + <location filename="../src/libclient/media/recordingmodel.cpp" line="189"/> + <source>Recordings</source> + <translation>Optagelser</translation> + </message> + <message> + <location filename="../src/libclient/media/recordingmodel.cpp" line="259"/> + <source>Text messages</source> + <translation>Tekstbeskeder</translation> + </message> + <message> + <location filename="../src/libclient/media/recordingmodel.cpp" line="264"/> + <source>Audio/Video</source> + <translation>Lyd/Video</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_de.ts b/translations/lrc_de.ts new file mode 100644 index 0000000000000000000000000000000000000000..3fd32e09eb976f2b0018086cd5d49c054402766d --- /dev/null +++ b/translations/lrc_de.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="de" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>lch</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Halten</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Sprechend</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>FEHLER</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Eingehend</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Rufaufbau</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Verbindet</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Suchen</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Inaktiv</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Abgeschlossen</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Zeitüberscheitung</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Teilnehmer beschäftigt</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Kommunikation hergestellt</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Einladung erhalten</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Kontakt hinzugefügt</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation>%1 wurde eingeladen beizutreten</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 ist beigetreten</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 hat die Unterhaltung verlassen</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation>%1 wurde entfernt</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation>%1 wurde erneut hinzugefügt</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation>Schwarm erstellt</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Ausgehender Anruf</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Eingehender Anruf</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Ausgehender Anruf fehlgeschlagen</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Verpasster eingehender Anruf</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Einladung angenommen</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>Standard</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Null</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Versuche</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Klingelt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>Wird weitergeleitet</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>In Warteschlange</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>Fortschritt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>OK</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Angenommen</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Mehrere Wahlmöglichkeiten</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Permanent verschoben</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Vorübergehend verschoben</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Proxy nutzen</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Alternativer Dienst</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Ungültige Anfrage</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Nicht autorisiert</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Zahlung notwendig</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Unzulässig</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Nicht gefunden</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Methode nicht zulässig</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>Nicht annehmbar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Proxy Authentifizierung notwendig</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Anfragezeitüberschreitung</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Verschwunden</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Anfrage zu groß</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>Anfragen-URI zu lang</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Medientyp nicht unterstützt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>URI-Schema nicht unterstützt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Ungültige Erweiterung</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Erweiterung notwendig</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Sitzungstimer zu klein</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Intervall zu kurz</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Temporär nicht verfügbar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>Anruf TSX existiert nicht</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Schleife erkannt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Zu viele Hops</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Adresse unvollständig</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>Nicht eindeutig</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Beschäftigt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Anfrage terminiert</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Ungültiges Ereignis</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Anfrage aktualisiert</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Anfrage ausstehend</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Nicht entschlüsselbar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Interner Serverfehler</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Nicht implementiert</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Ungültiges Gateway</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Dienst nicht verfügbar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Serverzeitüberschreitung</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Version nicht unterstützt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Nachricht zu groß</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Vorbedingung fehlgeschlagen</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Ãœberall beschäftigt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Anruf abgelehnt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>Existiert nirgendswo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>Nirgendwo annehmbar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Chatansicht ausblenden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Starte Videoanruf</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Verfügbare Plugins anzeigen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Starte Audioanruf</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Zu Konversationen hinzufügen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Kontakt entsperren</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Senden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>Optionen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Zum Ende der Unterhaltung scrollen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Datei senden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Emoji einfügen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Videonachricht hinterlassen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Sprachnachricht hinterlassen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>In Downloads kopieren</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>Schreibe an {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>hat Ihnen eine Gesprächsanfrage gesendet.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Hallo, möchten Sie an der Unterhaltung teilnehmen?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Sie haben die Gesprächsanfrage angenommen.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>Wir warten auf ein anderes Gerät, um das Gespräch zu synchronisieren.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Annehmen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Ablehnen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>Kein Kontakt möglich</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>Wartet auf Kontakt</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>Eingehende Ãœbertragung</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>Zeitüberschreitung beim Warten auf Kontakt</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Sperren</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Hinweis: Durch Interaktion wird ein Kontakt erstellt.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>ist nicht in Ihren Kontakten</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Hinweis: Durch Senden einer Nachricht wird diese Einladung automatisch angenommen.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>vor {0} Tagen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>vor {0} Stunden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>vor {0} Minuten</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Abgebrochen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>Laufend</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>vor %d Tagen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>vor %d Stunden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>vor %d Minuten</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>vor einem Tag</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>vor einer Stunde</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>gerade eben</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Fehler</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Löschen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Wiederholen</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Suchen…</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>Ungültige ID</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Benutzername nicht gefunden</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>Konnte nicht nachschlagen...</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Ungültiges URI-Schema</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_de_DE.ts b/translations/lrc_de_DE.ts new file mode 100644 index 0000000000000000000000000000000000000000..248746bba4736116ed3d46c1f6cd2570a88a841b --- /dev/null +++ b/translations/lrc_de_DE.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="de_DE" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Ich</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>In die Warteschleife schalten</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Sprechen</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>FEHLER</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Eingehend</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Anrufen</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Verbinden</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Suche</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Inaktiv</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Erledigt</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Zeitüberschreitung</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Gegenstelle ist beschäftigt</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Verbindung hergestellt</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Einladung erhalten</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Kontakt hinzugefügt</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation>%1 wurde eingeladen beizutreten</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 ist beigetreten</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 hat die Unterhaltung verlassen</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation>%1 wurde entfernt</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation>%1 wurde erneut hinzugefügt</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation>Schwarm erstellt</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Ausgehende Anruf</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Eingehender Anruf</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Verpasster ausgehender Anruf</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Verpasster eingehender Anruf</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Einladung akzeptiert</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>Standard</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Nichts</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Versuche</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Klingeln</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>Wird weitergeleitet</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>In der Warteschlange</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>Fortschritt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Okay</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Akzeptiert</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Mehrfachauswahl</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Dauerhaft verschoben</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Zeitlich begrenzt verschoben</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Benutze einen Proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Alternativer Dienst</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Unmögliche Anfrage</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Keine Berechtigung</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Bezahlung erforderlich</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Nicht erlaubt!</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Nicht gefunden!</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Diese Art und Weise ist nicht erlaubt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>Inakzeptabel</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Für diesen Proxy werden Anmeldedaten benötigt!</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Zeitüberschreitung der Anforderung</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Verlassen</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Das Anfrageobjekt ist zu groß!</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>Die formulierte Anfrage ist zu lang</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Nicht unterstützter Medientyp</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Diese Art die Anfrage zu formulieren wird nicht unterstützt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Fehlerhafte Erweiterung</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Eine Erweiterung wird benötigt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Sitzungstimer zu klein</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Intervall zu kurz</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Temporär nicht verfügbar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>Anruf TSX existiert nicht</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Unendlicher Zirkelbezug erkannt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Zu viele Netzwerksprünge</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Adresse unvollständig</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>Nicht eindeutig</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Besetzt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Anfrage erfolglos abgebrochen</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Ungültiges Ereignis</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Anfrage aktualisiert</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Anfrage ausstehend</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Nicht entschlüsselbar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Interner Server Fehler</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Nicht implementiert</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Ungültige Zwischenstelle</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Dienst nicht verfügbar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Serverzeitüberschreitung</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Version nicht unterstützt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Nachricht zu groß</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Vorbedingung fehlgeschlagen</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Ãœberall beschäftigt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Anruf abgelehnt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>Existiert nirgendswo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation> Nirgendwo annehmbar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Chat verbergen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Starte Videoanruf</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Verfügbare Plugins anzeigen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Audio-Anruf beginnen </translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Zur Unterhaltung hinzufügen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Kontakt wieder erlauben</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Senden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>Optionen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Zum Ende der Unterhaltung scrollen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Datei senden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Emoji hinzufügen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Video-Nachricht hinterlassen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Audio-Nachricht hinterlassen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Zu Downloads kopieren</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>Nach [0] schreiben</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>hat dir eine Konversationsanfrage gesendet.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Hallo, möchtest du an der Unterhaltung teilnehmen?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Sie haben die Unterhaltungsanfrage angenommen.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>Wir warten auf ein anderes Gerät, um das Gespräch zu synchronisieren.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Akzeptieren</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Ablehnen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>Kontakt kann nicht hergestellt werden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>Auf Kontakt warten</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>Eingehende Ãœbertragung</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>Frist für das Warten auf Kontakt verstrichen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Blockieren</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Hinweis: eine Bedienung wird einen neuen Kontakt anlegen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>ist nicht in Ihrer Kontaktliste</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Hinweis: Sie können diese Einladung automatisch annehmen, indem sie eine Nachricht schicken. </translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>vor {0} Tagen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>vor {0} Stunden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>vor {0} Minuten</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Abgebrochen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>Ãœbertragung läuft</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>vor %d Tagen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>vor %d Stunden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>vor %d Minuten</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>vor einem Tag</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>vor einer Stunde</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>gerade eben</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Fehlgeschlagen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Löschen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Wiederholen</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Suche ...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>Ungültige Identifikation (ID)</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Benutzername nicht gefunden</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>Nicht gefunden ...</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Diese Art die Anfrage zu formulieren wird nicht unterstützt</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_el.ts b/translations/lrc_el.ts new file mode 100644 index 0000000000000000000000000000000000000000..79c3e300cfe4c7225d3401f54b752cf5647ab004 --- /dev/null +++ b/translations/lrc_el.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="el" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Εγώ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Αναμονή</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Μιλά</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>ΣΦΑΛΜΑ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Καλεί</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>ΣυνδÎεται</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Επικοινωνία επιτεÏχθηκε</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Η επαφή Ï€ÏοστÎθηκε</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>Ο χÏήστης %1 συμμετÎχει</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>ΕξεÏχόμενη κλήση</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>ΕισεÏχόμενη κλήση</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Αναπάντητη εξεÏχόμενη κλήση</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Αναπάντητη εισεÏχόμενη κλήση</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>Ï€Ïοεπιλογή</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Κουδουνίζει</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Εντάξει</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Αίτημα Εκτός ΧÏόνου</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>ΑπασχολημÎνο</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>ΑπόκÏυψη Ï€Ïοβολής συνομιλίας</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Αποστολή</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>ΚÏλιση στο Ï„Îλος της συνομιλίας</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Αποστολή αÏχείου</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Αποδοχή</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>ΆÏνηση</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>ΜπλοκάÏισμα</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>ΑκυÏώθηκε</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>ΔιαγÏαφή</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_en.ts b/translations/lrc_en.ts new file mode 100644 index 0000000000000000000000000000000000000000..23bd4441c500f6c7a3161e5831e160842bf15260 --- /dev/null +++ b/translations/lrc_en.ts @@ -0,0 +1,677 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE TS> +<TS version="2.1" language="en_US" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"></translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"></translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"></translation> + </message> +</context> +</TS> diff --git a/translations/lrc_en_GB.ts b/translations/lrc_en_GB.ts new file mode 100644 index 0000000000000000000000000000000000000000..76e830d1fba17435af56898cde1afaf6d34c634c --- /dev/null +++ b/translations/lrc_en_GB.ts @@ -0,0 +1,1460 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS language="en_GB" sourcelanguage="en" version="2.0"> +<context> + <name>Account</name> + <message> + <location filename="../src/libclient/account.cpp" line="307"/> + <source>Ready</source> + <extracomment>Account state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="309"/> + <source>Registered</source> + <extracomment>Account state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="313"/> + <source>Initializing</source> + <extracomment>Account state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="317"/> + <source>Error</source> + <extracomment>Account state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="321"/> + <source>Network unreachable</source> + <extracomment>Account state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="323"/> + <source>Host unreachable</source> + <extracomment>Account state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="311"/> + <source>Not registered</source> + <extracomment>Account state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="315"/> + <source>Trying…</source> + <extracomment>Account state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="319"/> + <source>Authentication failed</source> + <extracomment>Account state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="325"/> + <source>STUN configuration error</source> + <extracomment>Account state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="327"/> + <source>STUN server invalid</source> + <extracomment>Account state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="329"/> + <source>Service unavailable</source> + <extracomment>Account state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="331"/> + <source>Unacceptable</source> + <extracomment>Account state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="333"/> + <source>Invalid</source> + <extracomment>Account state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/account.cpp" line="335"/> + <source>Request timeout</source> + <extracomment>Account state</extracomment> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>AccountChecksModel</name> + <message> + <location filename="../src/libclient/securityevaluationmodel.cpp" line="438"/> + <source>Configuration</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>Call</name> + <message> + <location filename="../src/libclient/call.cpp" line="719"/> + <source>New</source> + <extracomment>Call state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="722"/> + <source>Ringing</source> + <extracomment>Call state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="725"/> + <source>Calling</source> + <extracomment>Call state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="728"/> + <source>Talking</source> + <extracomment>Call state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="731"/> + <source>Dialing</source> + <extracomment>Call state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="734"/> + <source>Hold</source> + <extracomment>Call state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="737"/> + <source>Failed</source> + <extracomment>Call state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="740"/> + <source>Busy</source> + <extracomment>Call state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="743"/> + <source>Transfer</source> + <extracomment>Call state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="746"/> + <source>Transfer hold</source> + <extracomment>Call state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="749"/> + <source>Over</source> + <extracomment>Call state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="752"/> + <source>Error</source> + <extracomment>Call state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="755"/> + <location filename="../src/libclient/call.cpp" line="860"/> + <source>Conference</source> + <extracomment>Call state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="758"/> + <source>Conference (hold)</source> + <extracomment>Call state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="761"/> + <source>ERROR</source> + <extracomment>Call state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="764"/> + <source>Searching for</source> + <extracomment>Call state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="767"/> + <source>Aborted</source> + <extracomment>Call state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="770"/> + <source>Communication established</source> + <extracomment>Call state</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="864"/> + <source>Unknown</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="2231"/> + <source>Account: </source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>CallModel</name> + <message> + <location filename="../src/libclient/callmodel.cpp" line="898"/> + <source>Calls</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>CallModelPrivate</name> + <message> + <location filename="../src/libclient/callmodel.cpp" line="533"/> + <location filename="../src/libclient/callmodel.cpp" line="558"/> + <source>Invalid account</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>CallPrivate</name> + <message> + <location filename="../src/libclient/call.cpp" line="1795"/> + <source>Aborted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/call.cpp" line="1816"/> + <source>No account registered!</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>CategorizedBookmarkModel</name> + <message> + <location filename="../src/libclient/categorizedbookmarkmodel.cpp" line="181"/> + <source>Most popular</source> + <extracomment>Most popular contacts</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/categorizedbookmarkmodel.cpp" line="299"/> + <source>Contacts</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>CategorizedContactModel</name> + <message> + <location filename="../src/libclient/categorizedcontactmodel.cpp" line="401"/> + <source>Contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="129"/> + <source>Empty</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="135"/> + <location filename="../src/libclient/private/sortproxies.cpp" line="153"/> + <source>Unknown</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="141"/> + <source>Never</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="147"/> + <source>Other</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>CategorizedHistoryModel</name> + <message> + <location filename="../src/libclient/categorizedhistorymodel.cpp" line="412"/> + <source>History</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>ChainOfTrustModel</name> + <message> + <location filename="../src/libclient/chainoftrustmodel.cpp" line="173"/> + <source>Chain of trust</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>CollectionModel</name> + <message> + <location filename="../src/libclient/collectionmodel.cpp" line="279"/> + <source>Name</source> + <translation>Name</translation> + </message> +</context> +<context> + <name>ContactSortingCategoryModel</name> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="49"/> + <source>Name</source> + <translation>Name</translation> + </message> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="50"/> + <source>Organisation</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="51"/> + <source>Recently used</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="52"/> + <source>Group</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="53"/> + <source>Department</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>HistorySortingCategoryModel</name> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="57"/> + <source>Date</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="58"/> + <source>Name</source> + <translation>Name</translation> + </message> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="59"/> + <source>Popularity</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="60"/> + <source>Duration</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/private/sortproxies.cpp" line="61"/> + <source>Total time</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>HistoryTimeCategoryModel</name> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="50"/> + <source>Today</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="51"/> + <source>Yesterday</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="58"/> + <source>Two weeks ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="59"/> + <source>Three weeks ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="57"/> + <source>A week ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="60"/> + <source>A month ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="61"/> + <source>Two months ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="62"/> + <source>Three months ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="63"/> + <source>Four months ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="64"/> + <source>Five months ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="65"/> + <source>Six months ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="66"/> + <source>Seven months ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="67"/> + <source>Eight months ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="68"/> + <source>Nine months ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="69"/> + <source>Ten months ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="70"/> + <source>Eleven months ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="71"/> + <source>Twelve months ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="72"/> + <source>A year ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="73"/> + <source>Very long time ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/historytimecategorymodel.cpp" line="74"/> + <source>Never</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>InstantMessagingModel</name> + <message> + <location filename="../src/libclient/media/textrecording.cpp" line="816"/> + <source>Me</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>MacroModel</name> + <message> + <location filename="../src/libclient/macromodel.cpp" line="157"/> + <source>Macros</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/macromodel.cpp" line="263"/> + <source>New</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/macromodel.cpp" line="264"/> + <source>Other</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>MacroModelPrivate</name> + <message> + <location filename="../src/libclient/macromodel.cpp" line="77"/> + <source>Other</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>NumberCategoryModel</name> + <message> + <location filename="../src/libclient/numbercategorymodel.cpp" line="56"/> + <source>Uncategorized</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>PersonModel</name> + <message> + <location filename="../src/libclient/personmodel.cpp" line="170"/> + <source>Persons</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>PhoneDirectoryModel</name> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="234"/> + <source>This account does not support presence tracking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="237"/> + <source>No associated account</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="305"/> + <source>URI</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="305"/> + <source>Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="305"/> + <source>Person</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="305"/> + <source>Account</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="305"/> + <source>State</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="305"/> + <source>Call count</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="305"/> + <source>Week count</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="306"/> + <source>Trimester count</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="306"/> + <source>Have Called</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="306"/> + <source>Last used</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="306"/> + <source>Name_count</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="306"/> + <source>Total (in seconds)</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="306"/> + <source>Popularity_index</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="307"/> + <source>Bookmarked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="307"/> + <source>Tracked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="307"/> + <source>Present</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="307"/> + <source>Presence message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="307"/> + <source>UID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="307"/> + <source>Has certificate</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/phonedirectorymodel.cpp" line="307"/> + <source>Registered name</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>PresenceStatusModel</name> + <message> + <location filename="../src/libclient/presencestatusmodel.cpp" line="197"/> + <source>Name</source> + <translation>Name</translation> + </message> + <message> + <location filename="../src/libclient/presencestatusmodel.cpp" line="197"/> + <source>Message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/presencestatusmodel.cpp" line="197"/> + <source>Color</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/presencestatusmodel.cpp" line="197"/> + <source>Present</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/presencestatusmodel.cpp" line="197"/> + <source>Default</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/presencestatusmodel.cpp" line="308"/> + <location filename="../src/libclient/presencestatusmodel.cpp" line="361"/> + <source>Custom</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/presencestatusmodel.cpp" line="308"/> + <location filename="../src/libclient/presencestatusmodel.cpp" line="310"/> + <location filename="../src/libclient/presencestatusmodel.cpp" line="354"/> + <location filename="../src/libclient/presencestatusmodel.cpp" line="361"/> + <source>N/A</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>ProfileModel</name> + <message> + <location filename="../src/libclient/profilemodel.cpp" line="637"/> + <source>Profiles</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>ProfileModelPrivate</name> + <message> + <location filename="../src/libclient/profilemodel.cpp" line="751"/> + <source>New profile</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/certificate.cpp" line="42"/> + <source>Has a private key</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="43"/> + <source>Is not expired</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="44"/> + <source>Has strong signing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="45"/> + <source>Is not self signed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="46"/> + <source>Have a matching key pair</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="47"/> + <source>Has the right private key file permissions</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="48"/> + <source>Has the right public key file permissions</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="49"/> + <source>Has the right private key directory permissions</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="50"/> + <source>Has the right public key directory permissions</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="51"/> + <source>Has the right private key directory location</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="52"/> + <source>Has the right public key directory location</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="53"/> + <source>Has the right private key SELinux attributes</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="54"/> + <source>Has the right public key SELinux attributes</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="55"/> + <source>The certificate file exist and is readable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="56"/> + <source>The file is a valid certificate</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="57"/> + <source>The certificate has a valid authority</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="58"/> + <source>The certificate has a known authority</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="59"/> + <source>The certificate is not revoked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="60"/> + <source>The certificate authority match</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="61"/> + <source>The certificate has the expected owner</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="62"/> + <source>The certificate is within its active period</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="90"/> + <source>Expiration date</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="91"/> + <source>Activation date</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="92"/> + <source>Require a private key password</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="93"/> + <source>Public signature</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="94"/> + <source>Version</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="95"/> + <source>Serial number</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="96"/> + <source>Issuer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="97"/> + <source>Subject key algorithm</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="98"/> + <source>Common name (CN)</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="99"/> + <source>Name (N)</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="100"/> + <source>Organization (O)</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="101"/> + <source>Signature algorithm</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="102"/> + <source>Md5 fingerprint</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="103"/> + <source>Sha1 fingerprint</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="104"/> + <source>Public key ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="105"/> + <source>Issuer domain name</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="106"/> + <source>Next expected update</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificate.cpp" line="107"/> + <source>Outgoing server</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificatemodel.cpp" line="183"/> + <source>Local certificate store</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificatemodel.cpp" line="267"/> + <location filename="../src/libclient/localprofilecollection.cpp" line="221"/> + <source>Default</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificatemodel.cpp" line="267"/> + <source>Certificate not associated with a group</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificatemodel.cpp" line="397"/> + <source>A certificate</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificatemodel.cpp" line="397"/> + <source>An organisation</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificatemodel.cpp" line="420"/> + <source>Details</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificatemodel.cpp" line="420"/> + <source>The content of the certificate</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificatemodel.cpp" line="421"/> + <source>Checks</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificatemodel.cpp" line="421"/> + <source>Various security related information</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/certificatemodel.cpp" line="610"/> + <source>Header</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/daemoncertificatecollection.cpp" line="148"/> + <source>Daemon certificate store</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/daemoncertificatecollection.cpp" line="152"/> + <source>%1 banned list</source> + <extracomment>The list of banned certificates for this account</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/daemoncertificatecollection.cpp" line="155"/> + <source>%1 allowed list</source> + <extracomment>The list of allowed certificates for this account</extracomment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/daemoncertificatecollection.cpp" line="160"/> + <location filename="../src/libclient/foldercertificatecollection.cpp" line="199"/> + <source>Certificate</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/extensions/presencecollectionextension.cpp" line="38"/> + <source>Presence tracking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/extensions/securityevaluationextension.cpp" line="63"/> + <source>Security evaluation</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/fallbackpersoncollection.cpp" line="196"/> + <source>Contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="532"/> + <source>Bookmark</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/localhistorycollection.cpp" line="196"/> + <source>Local history</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/localhistorycollection.cpp" line="201"/> + <source>History</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/localrecordingcollection.cpp" line="101"/> + <source>Local recordings</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/localrecordingcollection.cpp" line="106"/> + <location filename="../src/libclient/localtextrecordingcollection.cpp" line="171"/> + <source>Recording</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/localringtonecollection.cpp" line="221"/> + <source>Local ringtones</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/localringtonecollection.cpp" line="226"/> + <source>Ringtone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/localtextrecordingcollection.cpp" line="166"/> + <source>Local text recordings</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/numbercategory.cpp" line="72"/> + <source>Phone number types</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/numbercategorymodel.cpp" line="186"/> + <source>Other</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/protocolmodel.cpp" line="50"/> + <source>Ring Account</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/protocolmodel.cpp" line="51"/> + <source>SIP Account</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="315"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/securityevaluationmodel.cpp" line="38"/> + <source>TLS is disabled, the negotiation won't be encrypted. Your communication will be vulnerable to snooping</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/securityevaluationmodel.cpp" line="40"/> + <source>Your certificate and authority don't match, if your certificate require an authority, it won't work</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/securityevaluationmodel.cpp" line="41"/> + <source>The outgoing server specified doesn't match the hostname or the one included in the certificate</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/securityevaluationmodel.cpp" line="42"/> + <source>The "verify incoming certificate" option is disabled, this leave you vulnerable to man in the middle attack</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/securityevaluationmodel.cpp" line="43"/> + <source>The "verify answer certificate" option is disabled, this leave you vulnerable to man in the middle attack</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/securityevaluationmodel.cpp" line="44"/> + <source>None of your certificate provide a private key, this is required. Please select a private key or use a certificate with one built-in</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/securityevaluationmodel.cpp" line="47"/> + <source>No certificate authority is provided, it won't be possible to validate if the answer certificates are valid. Some account may also not work.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/securityevaluationmodel.cpp" line="46"/> + <source>No certificate has been provided. This is, for now, unsupported by Ring</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/securityevaluationmodel.cpp" line="37"/> + <source>Your media streams are not encrypted, please enable SDES</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/securityevaluationmodel.cpp" line="50"/> + <source>Your certificate is expired, please contact your system administrator.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/securityevaluationmodel.cpp" line="51"/> + <source>Your certificate is self signed. This break the chain of trust.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/tlsmethodmodel.cpp" line="64"/> + <source>Default</source> + <comment>Default TLS protocol version</comment> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="517"/> + <location filename="../src/libclient/useractionmodel.cpp" line="759"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="60"/> + <location filename="../src/libclient/useractionmodel.cpp" line="518"/> + <location filename="../src/libclient/useractionmodel.cpp" line="771"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="62"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="64"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="66"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="68"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="70"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="72"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="74"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="76"/> + <location filename="../src/libclient/api/call.h" line="82"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="78"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="80"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="84"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="519"/> + <source>Mute audio</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="520"/> + <source>Mute video</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="521"/> + <source>Server transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="522"/> + <source>Record</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="523"/> + <location filename="../src/libclient/useractionmodel.cpp" line="789"/> + <source>Hangup</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="524"/> + <source>Join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="525"/> + <source>Add new</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="526"/> + <source>Toggle video</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="527"/> + <source>Add a contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="528"/> + <source>Add to existing contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="529"/> + <source>Delete contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="530"/> + <source>Email contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="531"/> + <source>Copy contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="534"/> + <source>Add phone number</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="535"/> + <source>Call again</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="536"/> + <source>Edit contact details</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="537"/> + <source>Remove from history</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="786"/> + <source>Remove</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="756"/> + <source>Call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="533"/> + <source>Open chat</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="768"/> + <source>Unhold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/useractionmodel.cpp" line="779"/> + <source>Cancel</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/localprofilecollection.cpp" line="148"/> + <source>Local profiles</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/localprofilecollection.cpp" line="153"/> + <source>Profile Collection</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/peerprofilecollection.cpp" line="142"/> + <source>Peer profiles</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/peerprofilecollection.cpp" line="147"/> + <source>Peers Profiles Collection</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/conversationmodel.cpp" line="1265"/> + <location filename="../src/libclient/conversationmodel.cpp" line="1649"/> + <location filename="../src/libclient/conversationmodel.cpp" line="1909"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/conversationmodel.cpp" line="1266"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/conversationmodel.cpp" line="1308"/> + <location filename="../src/libclient/conversationmodel.cpp" line="1315"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/conversationmodel.cpp" line="1524"/> + <source>📞 Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/conversationmodel.cpp" line="1526"/> + <source>📞 Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/conversationmodel.cpp" line="1539"/> + <source>📞 Outgoing call - </source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/conversationmodel.cpp" line="1542"/> + <source>📞 Incoming call - </source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/conversationmodel.cpp" line="1546"/> + <source>🕽 Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/conversationmodel.cpp" line="1548"/> + <source>🕽 Missed incoming call</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>RingDeviceModel</name> + <message> + <location filename="../src/libclient/ringdevicemodel.cpp" line="110"/> + <source>ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/ringdevicemodel.cpp" line="112"/> + <source>Name</source> + <translation>Name</translation> + </message> +</context> +<context> + <name>SecurityEvaluationModelPrivate</name> + <message> + <location filename="../src/libclient/securityevaluationmodel.cpp" line="683"/> + <source>Authority</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>TlsMethodModel</name> + <message> + <location filename="../src/libclient/tlsmethodmodel.cpp" line="101"/> + <source>Automatic</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>Video::SourceModel</name> + <message> + <location filename="../src/libclient/video/sourcemodel.cpp" line="95"/> + <source>NONE</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/video/sourcemodel.cpp" line="101"/> + <source>SCREEN</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/video/sourcemodel.cpp" line="107"/> + <source>FILE</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="393"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="747"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="750"/> + <source>Not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="753"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="364"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>media::RecordingModel</name> + <message> + <location filename="../src/libclient/media/recordingmodel.cpp" line="189"/> + <source>Recordings</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/media/recordingmodel.cpp" line="259"/> + <source>Text messages</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/media/recordingmodel.cpp" line="264"/> + <source>Audio/Video</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_eo.ts b/translations/lrc_eo.ts new file mode 100644 index 0000000000000000000000000000000000000000..38c469cedd9743e36a2ef89dd298cf3d59c48565 --- /dev/null +++ b/translations/lrc_eo.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="eo" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Mi</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Deteni</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Parolanta</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>ERARO</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Vokanta</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Konektita</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 aliÄis</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Eliranta voko</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Eniranta voko</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>defaÅlta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>SonoriÄanta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Bone</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>EltempiÄo de Peto</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Okupata</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>KaÅi babilejon</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Sendi</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Akcepti</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Rifuzi</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Nuligita</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Forigi</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_es.ts b/translations/lrc_es.ts new file mode 100644 index 0000000000000000000000000000000000000000..a0cfd21d6a933ffff51a2c9021fb14e294d7897f --- /dev/null +++ b/translations/lrc_es.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="es" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Yo</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Espera</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Hablando</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>ERROR</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Llamada entrante</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Llamando</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Conectando</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Buscando</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Inactivo</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Terminado</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Tiempo de expiración</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Par Ocupado</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Comunicación establecida</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Invitación recibida</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Contacto añadido</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation>%1 fue invitado a unirse</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 se ha unido</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 ha salido</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation>%1 fue eliminado</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation>%1 fue reincorporado</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation>Enjambre creado</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Llamada saliente</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Llamada entrante</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Llamada saliente perdida</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Llamada entrante perdida</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Invitación aceptada</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>Por defecto</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Inválido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Conectando</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Sonando</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>Derivando llamada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>En cola</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>Progreso</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Aceptar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Aceptada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Varias opciones</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Movido definitivamente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Movido temporalmente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Usar proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Servicio alternativo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Solicitud incorrecta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>No autorizado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Pago requerido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Denegado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>No encontrado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Método no permitido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>No aceptable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Autenticación del proxy requerida</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Tiempo de repuesta agotado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Acabado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Entidad solicitada demasiado larga</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>Solicitud URI demasiado larga</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Formato multimedia no soportado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Esquema de URI no soportado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Extensión no válida</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Extensión requerida</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Temporizador de sesión demasiado pequeño</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Intervalo demasiado breve</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Temporalmente no disponible</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>La llamada TSX no existe</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Bucle detectado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Demasiados saltos -too many hops.</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Dirección incompleta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>Ambiguo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Ocupado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Solicitud terminada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Evento no válido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Solicitud actualizada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Solicitud pendiente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Indecifrable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Error del servidor interno</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>No implementado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Puerta de enlace no válida</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Servicio no disponible</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Expiró el tiempo de espera del servidor</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Versión no soportada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Mensaje demasiado extenso</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Falla de la condición previa</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Ocupado en todas partes</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Llamada rechazada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>No existe en ningún lugar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>No aceptable en ningún lugar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Ocultar el chat</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Realizar videollamada</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Mostrar complementos disponibles</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Realizar llamada de audio</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Añadir a conversaciones</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>contacto unban</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Enviar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>Opciones</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Desplazar hasta el final de la conversación</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Enviar archivo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Añadir emoji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Dejar mensaje de vÃdeo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Dejar mensaje de audio</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Copiar a descargas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>Escribir a {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>te ha enviado una solicitud de conversación.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Hola, ¿quieres unirte a la conversación?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Has aceptado la solicitud de conversación.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>Esperando a otro dispositivo para sincronizar la conversación.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Aceptar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>No aceptar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>No se pudo contactar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>Esperando al contacto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>Transferencia entrante</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>Expiró el tiempo de espera al contacto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Bloquear</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Nota: La interacción creará un nuevo contacto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>no está en tus contactos</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Nota: Puedes aceptar esta invitación automáticamente enviando un mensaje</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>Hace {0} dÃas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>Hace {0} horas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>Hace {0} minutos</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Cancelado</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>En curso</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>Hace 1%d dÃas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>Hace 1%d horas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>Hace %d minutos</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>hace un dÃa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>hace una hora</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>justo ahora</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Error</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Borrar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Reintentar</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Buscando</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>ID inválida</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Nombre de usuario no encontrado</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>No se ha podido buscar...</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Mal esquema de URI</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_es_AR.ts b/translations/lrc_es_AR.ts new file mode 100644 index 0000000000000000000000000000000000000000..90f2408c6970ec2453530673dfb838337005405d --- /dev/null +++ b/translations/lrc_es_AR.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="es_AR" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Yo</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Espera</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Hablando</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>ERROR</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Entrante</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Llamando</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Conectando</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Buscando</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Inactivo</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Finalizado</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Expiró el tiempo de espera</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Par ocupado</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Comunicación establecida</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Invitación recibida</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Contacto añadido</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation>%1 fue invitado a unirse</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 se ha unido</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 ha salido</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation>%1 fue eliminado</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation>%1 fue reincorporado</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation>Enjambre creado</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Llamada saliente</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Llamada entrante</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Llamada saliente perdida</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Llamada entrante perdida</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Invitación aceptada</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>Por defecto</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Inválido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Intentando</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Sonando</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>Derivando llamada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>Llamada en espera</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>Progreso</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Aceptar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Aceptada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Múltiples elecciones</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Movido definitivamente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Movido temporalmente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Usar proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Servicio alternativo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Solicitud incorrecta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>No autorizado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Pago requerido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Denegado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>No encontrado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Método no permitido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>No aceptable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Se requiere autenticación del proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Tiempo de espera caducado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Retirado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Entidad solicitada demasiado grande</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>URI solicitada demasiado extensa</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Tipo de medio no soportado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Esquema URI no soportado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Extensión errónea</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Extensión requerida</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Temporizador de sesión demasiado bajo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Intervalo demasiado breve</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Temporalmente no disponible</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>Llamada TSX inexistente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Bucle detectado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Demasiados saltos</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Dirección incompleta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>Ambiguo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Ocupado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Solicitud terminada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Evento erróneo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Solicitud actualizada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Solicitud pendiente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Indescifrable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Error de servidor interno</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>No implementado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Puerta de salida errónea</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Servicio no disponible</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Tiempo de espera del servidor agotado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Versión no soportada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Mensaje demasiado extenso</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Falla de precondición</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Ocupado en todas partes</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Llamada rechazada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>No existe en ningún lado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>No aceptable en ningún lado</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Ocultar vista de conversación</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Realizar videollamada</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Mostrar complementos disponibles</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Realizar audiollamada</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Agregar a conversaciones</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Desbloquear contacto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Enviar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>Opciones</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Desplazar hasta el final de la conversación</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Enviar archivo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Añadir emoji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Dejar mensaje de video</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Dejar mensaje de audio</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Copiar a descargas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>Escribir a {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>te ha enviado una solicitud de conversación.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Hola, ¿querés unirte a la conversación?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Has aceptado la solicitud de conversación.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>Esperando a otro dispositivo para sincronizar la conversación.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Aceptar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Rechazar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>No se pudo contactar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>Esperando al contacto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>Transferencia entrante</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>Expiró el tiempo de espera al contacto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Bloquear</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Nota: una interacción creará un nuevo contacto.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>no está en tus contactos</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Nota: podés aceptar automáticamente esta invitación enviando un mensaje.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>Hace {0} dÃas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>Hace {0} horas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>Hace {0} minutos</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Cancelado</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>En curso</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>hace %d dÃas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>hace %d horas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>hace %d minutos</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>hace un dÃa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>hace una hora</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>hace un momento</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Falla</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Eliminar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Reintentar</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Buscando...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>ID inválido</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Nombre de usuario no encontrado</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>No se pudo buscar...</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Esquema URI erróneo</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_es_CO.ts b/translations/lrc_es_CO.ts new file mode 100644 index 0000000000000000000000000000000000000000..7c16e31308b01eb1bfc7f838e5b4e9723c14171d --- /dev/null +++ b/translations/lrc_es_CO.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="es_CO" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Yo</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Poner en espera</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Hablando</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>ERROR</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Entrante</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Llamando</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Conectado</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Buscando</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Inactivo</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Finalizado</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Expiró el tiempo de espera</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Par ocupado</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Comunicación establecida</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Invitación recibida</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Contacto añadido</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation>%1 fue invitado a unirse</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 se ha unido</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 ha salido</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation>%1 fue eliminado</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation>%1 fue reincorporado</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation>Enjambre creado</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Lllamando a </translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Llamada entrante</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Lllamada saliente perdida</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Llamada entrante perdida</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Invitación aceptada</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>por defecto</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Inválido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Conectando</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Marcando</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>Derivando llamada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>En cola</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>Progreso</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Aceptar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Aceptada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Varias opciones</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Movido definitivamente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Movido temporalmente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Usar proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Servicio alternativo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Solicitud incorrecta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>No autorizado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Pago requerido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Denegado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>No encontrado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Método no permitido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>No aceptable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Autenticación del proxy requerida</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Tiempo de espera caducado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Retirado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Entidad solicitada demasiado grande</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>URI solicitada demasiado extensa</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Tipo de medio no soportado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Esquema URI no soportado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Extensión errónea</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Extensión requerida</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Temporizador de sesión demasiado bajo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Intervalo demasiado breve</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Temporalmente no disponible</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>Llamada TSX inexistente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Bucle detectado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Demasiados saltos</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Dirección incompleta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>Ambiguo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Ocupado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Solicitud terminada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Evento erróneo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Solicitud actualizada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Solicitud pendiente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Indescifrable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Error de servidor interno</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>No implementado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Puerta de salida errónea</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Servicio no disponible</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Tiempo de espera del servidor agotado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Versión no soportada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Mensaje demasiado extenso</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Falla de precondición</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Ocupado en todas partes</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Llamada rechazada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>No existe en ningún lado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>No aceptable en ningún lado</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Ocultar vista de charla</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Hacer videollamada</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Mostrar complementos disponibles</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Hacer llamada de voz</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Agregar a conversaciones</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Desbloquear contacto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Enviar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>Opciones</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Desplazar hasta el final de la conversación</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Enviar archivo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Añadir emoji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Dejar mensaje de video</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Dejar mensaje de audio</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Copiar a descargas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>Escribir a {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>te ha enviado una solicitud de conversación.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Hola, ¿quieres unirte a la conversación?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Has aceptado la solicitud de conversación.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>Esperando a otro dispositivo para sincronizar la conversación.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Aceptar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Rechazar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>No se pudo contactar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>Esperando al contacto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>Transferencia entrante</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>Expiró el tiempo de espera al contacto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Bloquear</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Nota: la interacción creará un contacto nuevo.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>no está en tus contactos</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Nota: puede aceptar automáticamente esta invitación enviando un mensaje.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>Hace {0} dÃas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>Hace {0} horas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>Hace {0} minutos</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Cancelado</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>En curso</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>Hace %d dÃas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>hace %d horas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>hace %d minutos</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>hace un dÃa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>hace una hora</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>hace unos segundos</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Falló</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Borrar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Reintentar</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Buscando...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>ID inválido</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Nombre de usuario no encontrado</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>No se pudo buscar...</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Esquema URI erróneo</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_es_MX.ts b/translations/lrc_es_MX.ts new file mode 100644 index 0000000000000000000000000000000000000000..b4e68eeef6dedef2b68e2bb665ad6c81fe642554 --- /dev/null +++ b/translations/lrc_es_MX.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="es_MX" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Yo</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>En espera</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Hablando</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>ERROR</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Entrante</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Llamando</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Conectado</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Buscando</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Inactivo</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Finalizado</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Expiró el tiempo de espera</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Par ocupado</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Comunicación establecida</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Invitación recibida</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Contacto añadido</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation>%1 fue invitado a unirse</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 unió</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 abandonó</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation>%1 fue eliminado</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation>%1 fue reincorporado</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation>Enjambre creado</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Lllamando a </translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Llamada entrante</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Lllamada saliente perdida</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Llamada entrante perdida</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Invitación aceptada</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>predeterminado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Inválido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Conectando</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Marcando</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>Derivando llamada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>En cola</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>Progreso</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Aceptar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Aceptada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Varias opciones</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Movido definitivamente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Movido temporalmente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Usar proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Servicio alternativo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Solicitud incorrecta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>No autorizado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Pago requerido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Denegado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>No encontrado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Método no permitido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>No aceptable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Autenticación del proxy requerida</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Tiempo de espera caducado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Retirado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Entidad solicitada demasiado grande</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>URI solicitada demasiado extensa</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Tipo de medio no soportado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Esquema URI no soportado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Extensión errónea</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Extensión requerida</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Temporizador de sesión demasiado bajo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Intervalo demasiado breve</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Temporalmente no disponible</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>Llamada TSX inexistente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Bucle detectado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Demasiados saltos</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Dirección incompleta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>Ambiguo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Ocupado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Solicitud terminada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Evento erróneo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Solicitud actualizada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Solicitud pendiente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Indescifrable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Error de servidor interno</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>No implementado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Puerta de salida errónea</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Servicio no disponible</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Tiempo de espera del servidor agotado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Versión no soportada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Mensaje demasiado extenso</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Falla de precondición</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Ocupado en todas partes</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Llamada rechazada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>No existe en ningún lado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>No aceptable en ningún lado</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Ocultar vista de charla</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Hacer videollamada</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Mostrar complementos disponibles</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Realizar audiollamada</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Agregar a conversaciones</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Desbloquear contacto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>EnvÃar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>Opciones</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Desplazar hasta el final de la conversación</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Enviar archivo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Añadir emoji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Dejar mensaje de video</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Dejar mensaje de audio</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Copiar a descargas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>Escribir a {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>te ha enviado una solicitud de conversación.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Hola, ¿quieres unirte a la conversación?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Has aceptado la solicitud de conversación.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>Esperando a otro dispositivo para sincronizar la conversación.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Aceptar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Rechazar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>No se pudo contactar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>Esperando al contacto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>Transferencia entrante</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>Expiró el tiempo de espera al contacto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Bloquear</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Nota: la interacción creará un contacto nuevo.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>no está en tus contactos</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Nota: puede aceptar automáticamente esta invitación enviando un mensaje.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>Hace {0} dÃas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>Hace {0} horas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>Hace {0} minutos</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Cancelado</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>En curso</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>Hace %d dÃas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>hace %d horas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>hace %d minutos</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>hace un dÃa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>hace una hora</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>hace un momento</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Error</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Borrar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Reintentar</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Buscando...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>ID inválido</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Nombre de usuario no encontrado</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>No se pudo buscar...</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Esquema URI erróneo</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_et.ts b/translations/lrc_et.ts new file mode 100644 index 0000000000000000000000000000000000000000..747ecdeaa96a4494b9a04e3871181c12d69ac639 --- /dev/null +++ b/translations/lrc_et.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="et" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Helistab</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Ãœhendab</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 liitus</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>vaikesäte</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Heliseb</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Sobib</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Kinni</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Liigu kerides vestluse lõppu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Saada fail</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Tühistatud</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_et_EE.ts b/translations/lrc_et_EE.ts new file mode 100644 index 0000000000000000000000000000000000000000..30888cf98b37b3dd5c145d8350ee4c30e9c13882 --- /dev/null +++ b/translations/lrc_et_EE.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="et_EE" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Helistab</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Ãœhendab</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 liitus</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>vaikesäte</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Heliseb</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Sobib</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Kinni</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Liigu kerides vestluse lõppu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Saada fail</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Tühistatud</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_eu.ts b/translations/lrc_eu.ts new file mode 100644 index 0000000000000000000000000000000000000000..dbda9033dc2aacd2a4fd8f42c72783fe7befc82d --- /dev/null +++ b/translations/lrc_eu.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="eu" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Ni</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Esperoan</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Hizketan</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>ERROREA</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Jasotzen</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Konektatzen</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Bilatzen</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Gonbidapena jasota</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Kontaktua gehituta</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 sartu da</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Irteera-deia</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Sarrera-deia</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Galdutako irteera-deia</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Galdutako sarrera-deia</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>lehenetsia</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Deitzen</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Ados</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Lanpetuta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Bidali</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Bidali fitxategia</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Onartu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Ukatu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Bloketu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Bertan behera utzita</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Ezabatu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_fa.ts b/translations/lrc_fa.ts new file mode 100644 index 0000000000000000000000000000000000000000..df9b340d514870958a33ada7b4705834aa923063 --- /dev/null +++ b/translations/lrc_fa.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="fa" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>من</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Ù†Ú¯Ù‡ داشتن</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>در Øال صØبت</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>خطا</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>تماس ورودی</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>در Øال تماس</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>در Øال اتصال</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>در Øال جستجو</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>غیر Ùعال</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>پایان یاÙته</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>انقضا</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>همتا مشغول</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>ارتباط برقرار شد.</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>دعوت نامه دریاÙت شد</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>مخاطب اÙزوده شد</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 ملØÙ‚ شد</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 ترک کرد</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>تماس خروجی</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>تماس ورودی</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>تماس خروجی بی پاسخ</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>تماس ورودی بی پاسخ</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>دعوت پذیرÙته شد</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>پیش Ùرض</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>خالی</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>در Øال تلاش</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>در Øال زنگ خوردن</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>Ùرستاده شده است</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>در صÙ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>در جریان</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>خب</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>پذیرÙته‌شده</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>چندین انتخاب</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>برای همیشه منتقل شد</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>به طور موقت منتقل شد</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>استÙاده از پروکسی</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>سرویس جایگزین</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>درخواست بی‌اعتبار</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>غیرمجاز</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>مستلزم پرداخت</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>ممنوع</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>یاÙت نشد</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>روش مجاز نمی‌باشد</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>قابل‌قبول نیست</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>اØراز هویت پروکسی مورد نیاز است</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>زمان انقضای درخواست</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>از بین رÙته</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>درخواست بیش‌از‌Øد بزرگ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>درخواست URI بیش از Øد طولانی</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>نوع رسانه پشتیبانی‌نشده</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Ø·Ø±Ø URI پشتیبانی‌نشده</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>اÙزونه بی‌اعتبار</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>اÙزونه مورد‌نیاز است</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>زمان‌سنج جلسه خیلی Ú©ÙˆÚ†Ú© است</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>بازه زمانی خیلی کوتاه</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>به طور موقت در‌دسترس نیست</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>TSX تماس وجود ندارد</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Øلقه شناسایی شد</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>تعداد بیش‌از‌Øد پرش (گام)</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>آدرس ناقص</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>مبهم</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>مشغول</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>درخواست خاتمه یاÙت</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>رویداد بی‌اعتبار</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>درخواست به‌روز شد</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>درخواست در‌انتظار</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>غیرقابل رمز‌گشایی</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>خطای داخلی سرور</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>پیاه‌سازی نشده</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>دروازه بی‌اعتبار</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>سرویس غیر‌قابل‌دسترس</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>انقضای سرور</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>این نسخه پشتیبانی نمی‌شود</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>پیام بیش‌از‌Øد بزرگ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>پیش‌شرط ناموÙÙ‚</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>همه‌جا مشغول</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>تماس رد شد</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>هیچ‌جایی وجود ندارد</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>هیچ‎‌جا قابل قبول نیست</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>مخÙی‌کردن نمای Ú¯Ùتگو</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>قرار تماس ویدیویی بگذار</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>نمایش اÙزونه‌های موجود</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>قرار تماس صوتی بگذار</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>اÙزودن به Ú¯Ùتگو‌ها</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>رÙع ممنوعیت مخاطب</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>ارسال</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>تنظیمات</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>پرش به آخرین</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>ارسال Ùایل</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Ø´Ú©Ù„Ú© اضاÙÙ‡ کنید</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>یک پیام تصویری بگذارید</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>یک پیام صوتی بگذارید</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Ú©Ù¾ÛŒ در دانلودها</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>نوشتن به {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>برای شما درخواست مکالمه ارسال کرده است.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>سلام، آیا مایل به شرکت در این Ú¯Ùتگو هستید؟</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>شما درخواست مکالمه را پذیرÙته‌اید.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>ما منتظر دستگاه دیگری هستیم تا Ú¯Ùتگو را همگام‌سازی کند.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>پذیرش</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>رد کردن</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>برقراری تماس امکان‌پذیر نیست</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation> در انتظار برقراری تماس</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>انتقال ورودی</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>زمان انتظار برای تماس به پایان رسید</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>مسدود</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>توجه: یک تعامل مخاطبی جدید ایجاد می‌کند.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>در مخاطبین شما نیست</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>توجه: شما Ù…ÛŒ توانید با ارسال پیام به طور خودکار این دعوت را بپذیرید.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>{0} روز پیش</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>{0} ساعت قبل</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>{0} دقیقه قبل</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>لغو شده</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>در جریان</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>%d روز پیش</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>%d ساعت پیش</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>%d دقیقه قبل</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>یک روز پیش</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>یک ساعت پیش</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>همین الان</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>عدم موÙقیت</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>ØØ°Ù</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>تلاش دوباره</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>در Øال جستجو...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>شناسهٔ نامعتبر</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>نام کاربری پیدا نشد</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>ناتوانی در جستجو…</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>شمای نشانی بد</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_fa_IR.ts b/translations/lrc_fa_IR.ts new file mode 100644 index 0000000000000000000000000000000000000000..1d0e126e6930b97fcc08d3e722dcf8c154b96454 --- /dev/null +++ b/translations/lrc_fa_IR.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="fa_IR" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>من</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Ù†Ú¯Ù‡ داشتن</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>در Øال صØبت</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>خطا</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>تماس ورودی</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>در Øال تماس</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>در Øال اتّصال</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>در Øال جستجو</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>غیر Ùعال</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>پایان یاÙته</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>انقضا</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>همتا مشغول</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>ارتباط برقرار شد.</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>دعوت نامه دریاÙت شد</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>مخاطب اÙزوده شد</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 ملØÙ‚ شد</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 ترک کرد</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>تماس خروجی</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>تماس ورودی</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>تماس خروجی از دست رÙته</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>تماس ورودی از دست رÙته</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>دعوت پذیرÙته شد</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>پیش Ùرض</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>خالی</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>در Øال تلاش</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>در Øال زنگ خوردن</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>Ùرستاده شده است</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>در صÙ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>در جریان</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>خب</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>پذیرÙته‌شده</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>چندین انتخاب</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>برای همیشه منتقل شد</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>به طور موقت منتقل شد</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>استÙاده از پروکسی</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>سرویس جایگزین</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>درخواست بی‌اعتبار</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>غیرمجاز</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>مستلزم پرداخت</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>ممنوع</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>یاÙت نشد</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>روش مجاز نمی‌باشد</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>قابل‌قبول نیست</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>اØراز هویت پروکسی مورد نیاز است</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>زمان انقضای درخواست</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>از بین رÙته</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>درخواست بیش‌از‌Øد بزرگ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>درخواست URI بیش از Øد طولانی</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>نوع رسانه پشتیبانی‌نشده</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Ø·Ø±Ø URI پشتیبانی‌نشده</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>اÙزونه بی‌اعتبار</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>اÙزونه مورد‌نیاز است</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>زمان‌سنج جلسه خیلی Ú©ÙˆÚ†Ú© است</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>بازه زمانی خیلی کوتاه</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>به طور موقت در‌دسترس نیست</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>TSX تماس وجود ندارد</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Øلقه شناسایی شد</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>تعداد بیش‌از‌Øد پرش (گام)</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>آدرس ناقص</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>مبهم</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>مشغول</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>درخواست خاتمه یاÙت</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>رویداد بی‌اعتبار</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>درخواست به‌روز شد</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>درخواست در‌انتظار</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>غیرقابل رمز‌گشایی</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>خطای داخلی سرور</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>پیاه‌سازی نشده</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>دروازه بی‌اعتبار</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>سرویس غیر‌قابل‌دسترس</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>انقضای سرور</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>این نسخه پشتیبانی نمی‌شود</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>پیام بیش‌از‌Øد بزرگ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>پیش‌شرط ناموÙÙ‚</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>همه‌جا مشغول</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>تماس رد شد</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>هیچ‌جایی وجود ندارد</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>هیچ‎‌جا قابل قبول نیست</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>مخÙی‌کردن نمای Ú¯Ùتگو</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>قرار تماس ویدیویی بگذار</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>نمایش اÙزونه‌های موجود</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>قرار تماس صوتی بگذار</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>اÙزودن به Ú¯Ùتگو‌ها</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>رÙع ممنوعیت مخاطب</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>ارسال</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>تنظیمات</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>پرش به آخرین</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>ارسال Ùایل</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Ø´Ú©Ù„Ú© اضاÙÙ‡ کنید</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>یک پیام تصویری بگذارید</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>یک پیام صوتی بگذارید</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Ú©Ù¾ÛŒ در دانلودها</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>نوشتن به {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>برای شما درخواست مکالمه ارسال کرده است.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>سلام، آیا مایل به شرکت در این Ú¯Ùتگو هستید؟</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>شما درخواست مکالمه را پذیرÙته‌اید.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>ما منتظر دستگاه دیگری هستیم تا Ú¯Ùتگو را همگام‌سازی کند.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>پذیرش</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>رد کردن</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>برقراری تماس امکان‌پذیر نیست</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation> در انتظار برقراری تماس</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>انتقال ورودی</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>زمان انتظار برای تماس به پایان رسید</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>مسدود</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>توجه: یک تعامل مخاطبی جدید ایجاد می‌کند.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>در مخاطبین شما نیست</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>توجه: شما Ù…ÛŒ توانید با ارسال پیام به طور خودکار این دعوت را بپذیرید.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>{0} روز پیش</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>{0} ساعت قبل</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>{0} دقیقه قبل</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>لغو شده</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>در جریان</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>%d روز پیش</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>%d ساعت پیش</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>%d دقیقه قبل</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>یک روز پیش</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>یک ساعت پیش</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>همین الان</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>عدم موÙقیت</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>ØØ°Ù</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>تلاش دوباره</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>در Øال جستجو...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>شناسهٔ نامعتبر</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>نام کاربری پیدا نشد</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>ناتوانی در جستجو…</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>شمای نشانی بد</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_fi.ts b/translations/lrc_fi.ts new file mode 100644 index 0000000000000000000000000000000000000000..ace8a5f8a4c4bb98e3f9f8584bbc9f42c200340b --- /dev/null +++ b/translations/lrc_fi.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="fi" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Minä</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Pidossa</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Puhuu</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>VIRHE</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Saapuva</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Soittaa</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Yhdistää</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Etsintä</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Poissa</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Valmis</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Aikakatkaisu</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Käyttäjä varattu</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Yhteys muodostettu</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Kutsu vastaanotettu</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Yhteystieto lisätty</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 liittyi</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Lähtevä puhelu</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Saapuva puhelu</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Vastaamaton lähtevä puhelu</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Vastaamaton puhelu</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Kutsu hyväksytty</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>oletus</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Tyhjä</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Yritetään</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Soi</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>Välitetään eteenpäin</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>Jonossa</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>Edistyminen</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>OK</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Hyväksytty</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Useita vaihtoehtoja</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Siirretty pysyvästi</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Siirretty tilapäisesti</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Käytä välityspalvelinta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Vaihtoehtoinen palvelu</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Virheellinen pyyntö</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Luvaton</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Maksu vaaditaan</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Kielletty</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Ei löydy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Menetelmää ei sallita</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>Ei hyväksyttävä</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Välityspalvelimen todennus vaaditaan</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Pyyntö aikakatkaistu</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Mennyt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Pyyntö on liian suuri</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>Pyynnön verkko-osoite liian pitkä</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Ei tuettu mediatyyppi</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Verkko-osoitteen mallia ei tueta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Virheellinen laajennus</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Laajennus vaaditaan</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Istunnon ajastin on liian pieni</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Väli liian lyhyt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Tilapäisesti poissa käytöstä</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>TSX-puhelua ei ole</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Silmukka havaittu</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Liian monta hyppyä</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Osoite epätäydellinen</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>Epäselvä</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Varattu</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Pyyntö lopetettu</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Huono tapahtuma</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Pyyntö päivitetty</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Pyyntö odottaa</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Ei purettavissa</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Sisäinen palvelinvirhe</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Ei toteutettu</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Huono yhdyskäytävä</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Palvelua ei käytettävissä</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Palvelimen aikakatkaisu</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Versiota ei tueta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Viesti on liian suuri</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Ennakkoehdon virhe</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Varattu kaikkialla</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Puhelu evätty</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>Ei ole missään</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>Ei hyväksytä missään</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Piilota chat-näkymä</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Aloita videopuhelu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Näytä saatavat laajennukset</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Aloita äänipuhelu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Lisää keskusteluihin</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Poista esto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Lähetä</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>Vaihtoehdot</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Vieritä keskustelun loppuun</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Lähetä tiedosto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Lisää hymiö</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Jätä videoviesti</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Jätä ääniviesti</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Kopioi latauksiin</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>Kirjoittaa {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>on lähettänyt sinulle keskustelupyynnön.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Hei, haluatko liittyä keskusteluun?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Olet hyväksynyt keskustelupyynnön.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>Odotamme, että toinen laite tahdistaa keskustelun.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Hyväksy</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Kieltäydy</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>Yhteyden muodostaminen epäonnistui</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>Odotetaan yhteyttä</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>Saapuva siirto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>Aikakatkaisu odottavalle yhteydelle</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Estä</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Huomaa: yhteydenotto tekee uuden yhteystiedon.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>ei ole yhteystiedoissasi</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Huomaa: voit automaattisesti hyväksyä tämän kutsun lähettämällä viestin.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>{0} päivää sitten</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>{0} tuntia sitten</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>{0} minuuttia sitten</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Peruttu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>Käynnissä</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>%d päivää sitten</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>%d tuntia sitten</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>%d minuuttia sitten</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>yksi päivä sitten</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>yksi tunti sitten</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>juuri nyt</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Virhe</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Poista</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Yritä uudelleen</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Etsitään...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>Virheellinen tunnus</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Käyttäjää ei löydy</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>Ei voitu etsiä...</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Virheellinen verkko-osoitteen malli</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_fr.ts b/translations/lrc_fr.ts new file mode 100644 index 0000000000000000000000000000000000000000..f70529c5b51e51360e076d1e95ff9436999a572d --- /dev/null +++ b/translations/lrc_fr.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="fr" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Moi</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Mettre en attente</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>En cours</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>ERREUR</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Appel entrant</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Appel en cours</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>En cours de connexion</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Recherche</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Inactif</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Complété</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Expiré</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Interlocuteur occupé</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Communication établie</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Invitation reçue</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Contact ajouté</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation>%1 a été invité(e)</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 s'est joint</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 a quitté</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation>%1 a été exclu(e)</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation>%1 a été de nouveau rajouté(e)</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation>Le Swarm a été créé</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Appel sortant</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Appel entrant</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Appel sortant manqué</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Appel entrant manqué</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Invitation acceptée</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>défaut</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Null</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Essai en cours</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Sonne</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>En cours de transfert</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>Mis dans la file d'attente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>En cours</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>OK</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Accepté</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Choix multiples</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Définitivement déplacé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Temporairement déplacé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Utiliser un serveur délégataire</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Service alternatif</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Requête invalide</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Non authorisé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Payement nécessaire</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Interdit</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Introuvable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Méthode non permise</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>N'est pas acceptable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Authentification au serveur mandataire nécessaire</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Requête expirée</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Parti</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>L'élément demandé est trop gros</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>l'URI demandée est trop longue</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Type de média non supporté</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Schéma d'URI non supporté</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Mauvaise extension</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Extension nécessaire</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Compteur de session trop petit</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Intervalle trop court</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Temporairement non disponible</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>L'appel TSX n’existe pas</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Boucle détectée</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Trop de sauts</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Adresse incomplète</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>Ambigu</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Occupé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>La requête est terminée</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Événement incorrect</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Requête modifiée</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Requête en attente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Indéchiffrable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Erreur Interne du Serveur</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Non Implémenté</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Mauvaise passerelle</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Service indisponible</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Dépassement de délai du serveur</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Version non supportée</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Message Trop Large</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Échec de Précondition </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Occupé partout</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Appel refusé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>N'existe nul part</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>N'est pas acceptable ici</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Cacher la fenêtre de clavardage</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Faire un appel vidéo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Montrer les modules d'extension disponibles</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Faire un appel audio</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Ajouter aux conversations</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Débloquer le contact</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Envoyer</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>Options</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Faire défiler jusqu'à la fin de la conversation</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Envoyez un fichier</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Ajouter un émoji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Envoyer un message vidéo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Envoyer un message vocal</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Copier pour télécharger</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>Écrire à {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>vous a envoyé une demande de conversation</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Bonjour, souhaitez-vous rejoindre la conversation ?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Vous avez accepté la demande de conversation</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>Nous attendons de synchroniser la conversation à partir d'un autre appareil.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Accepter</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Refuser</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>Impossible de contacter l'interlocuteur</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>En attente de votre contact</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>Transfert entrant</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>Délai d'attente de votre contact dépassé</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Bloquer</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Remarque: une interaction créera un nouveau contact.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>ne fait pas parti de vos contacts</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Remarque: vous pouvez automatiquement accepter une invitation en lui répondant.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>Il y a {0} jours</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>il y a {0} heures</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>il y a {0} minutes</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Annulé</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>En cours</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>Il y a %d jours</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>Il y a %d heures</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>Il y a %d minutes</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>il y a une journée</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>il y a une heure</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>juste maintenant</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Échec</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Supprimer</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Réessaie</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Recherche en cours ...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>ID invalide</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Nom d'utilisateur non trouvé</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>Impossible de vérifier le nom d'utilisateur</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Schéma d'URI non supporté</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_fr_BE.ts b/translations/lrc_fr_BE.ts new file mode 100644 index 0000000000000000000000000000000000000000..e83bb27e24e637e8eac2376c80b685274f75a94b --- /dev/null +++ b/translations/lrc_fr_BE.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="fr_BE" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Moi</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Mettre en attente</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Appel en cours</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>ERREUR</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Appel entrant</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Appel en cours</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>En cours de connexion</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Recherche en cours</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Inactif</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Terminé</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Expiré</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Interlocuteur occupé</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Communication établie</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Invitation reçue</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Contact ajouté</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation>%1 a été invité(e)</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 s'est joint</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 a quitté</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation>%1 a été exclu(e)</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation>%1 a été de nouveau rajouté(e)</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation>Le Swarm a été créé</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Appel sortant</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Appel entrant</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Appel sortant manqué</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Appel entrant manqué</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Invitation acceptée</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>défaut</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Null</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Essai en cours</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Sonnerie en cours</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>En cours de transfert</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>Mis dans la file d'attente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>En cours</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>ok</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Accepté</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Choix multiples</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Définitivement déplacé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Temporairement déplacé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Utiliser un serveur délégataire</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Service alternatif</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Requête invalide</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Non authorisé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Payement nécessaire</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Interdit</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Introuvable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Méthode non permise</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>N'est pas acceptable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Authentification au serveur mandataire nécessaire</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Délai de la requête dépassé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Parti</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>L'élément demandé est trop gros</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>l'URI demandée est trop longue</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Type de média non supporté</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Schéma d'URI non supporté</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Mauvaise extension</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Extension nécessaire</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Compteur de session trop petit</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Intervalle trop court</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Temporairement non disponible</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>L'appel TSX n’existe pas</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Boucle détectée</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Trop de sauts</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Adresse incomplète</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>Ambigu</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Occupé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>La requête est terminée</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Événement incorrect</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Requête modifiée</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Requête en attente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Indéchiffrable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Erreur Interne du Serveur</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Non Implémenté</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Mauvaise passerelle</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Service indisponible</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Dépassement de délai du serveur</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Version non supportée</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Message Trop Large</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Échec de Précondition </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Occupé partout</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Appel refusé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>N'existe nul part</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>N'est pas acceptable ici</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Cacher la fenêtre de clavardage</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Faire un appel vidéo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Montrer les modules d'extension disponibles</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Faire un appel audio</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Ajouter aux conversations</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Débloquer le contact</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Envoyer</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>Options</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Faire défiler jusqu'à la fin de la conversation</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Envoyer fichier</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Ajouter un émoji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Envoyer un message vidéo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Envoyer un message vocal</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Copier pour télécharger</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>Écrire à {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>vous a envoyé une demande de conversation</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Bonjour, souhaitez-vous rejoindre la conversation ?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Vous avez accepté la demande de conversation</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>Nous attendons de synchroniser la conversation à partir d'un autre appareil.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Accepter</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Refuser</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>Impossible de contacter l'interlocuteur</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>En attente de votre contact</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>Transfert entrant</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>Délai d'attente de votre contact dépassé</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Bloquer</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Remarque: une interaction créera un nouveau contact.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>ne fait pas parti de vos contacts</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Remarque: vous pouvez automatiquement accepter une invitation en lui répondant.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>Il y a {0} jours</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>il y a {0} heures</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>il y a {0} minutes</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Annulé</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>En cours</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>Il y a %d jours</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>Il y a %d heures</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>Il y a %d minutes</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>il y a une journée</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>il y a une heure</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>juste maintenant</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Échec</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Supprimer</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Réessaie</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Recherche...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>ID invalide</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Nom d'utilisateur non trouvé</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>Impossible de vérifier le nom d'utilisateur</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Schéma d'URI non supporté</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_fr_CA.ts b/translations/lrc_fr_CA.ts new file mode 100644 index 0000000000000000000000000000000000000000..a00ccde84ca6b6f20ea8dcd3e8dea236c45e7806 --- /dev/null +++ b/translations/lrc_fr_CA.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="fr_CA" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Moi</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>tenir</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Appel en cours</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>ERREUR</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Appel entrant</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>appel en cours </translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Connexion en cours</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Recherche en cours</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Inactif</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Terminé</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Expiré</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Interlocuteur occupé</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Communication établie</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Invitation reçue</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Contact ajouté</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation>%1 a été invité(e)</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 s'est joint</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 a quitté</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation>%1 a été exclu(e)</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation>%1 a été de nouveau rajouté(e)</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation>Le Swarm a été créé</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Appel sortant</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Appel entrant</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Appel sortant manqué</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Appel entrant manqué</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Invitation acceptée</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>défaut</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Null</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Essai en cours</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Sonnerie en cours</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>En cours de transfert</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>Mis dans la file d'attente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>En cours</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>OK</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Accepté</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Choix multiples</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Définitivement déplacé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Temporairement déplacé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Utiliser un serveur délégataire</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Service alternatif</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Requête invalide</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Non authorisé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Payement nécessaire</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Interdit</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Introuvable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Méthode non permise</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>N'est pas acceptable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Authentification au serveur mandataire nécessaire</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Délai de la requête dépassé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Parti</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>L'élément demandé est trop gros</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>l'URI demandée est trop longue</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Type de média non supporté</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Schéma d'URI non supporté</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Mauvaise extension</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Extension nécessaire</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Compteur de session trop petit</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Intervalle trop court</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Temporairement non disponible</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>L'appel TSX n’existe pas</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Boucle détectée</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Trop de sauts</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Adresse incomplète</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>Ambigu</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Occupé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>La requête est terminée</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Événement incorrect</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Requête modifiée</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Requête en attente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Indéchiffrable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Erreur Interne du Serveur</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Non Implémenté</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Mauvaise passerelle</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Service indisponible</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Dépassement de délai du serveur</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Version non supportée</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Message Trop Large</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Échec de Précondition </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Occupé partout</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Appel refusé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>N'existe nul part</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>N'est pas acceptable ici</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Cacher la fenêtre de clavardage</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Faire un appel vidéo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Montrer les modules d'extension disponibles</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Faire un appel audio</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Ajouter aux conversations</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Débloquer le contact</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Envoyer</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>Options</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Faire défiler jusqu'à la fin de la conversation</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Envoyer fichier</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Ajouter un émoji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Envoyer un message vidéo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Envoyer un message vocal</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Copier pour télécharger</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>Écrire à {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>vous a envoyé une demande de conversation</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Bonjour, souhaitez-vous rejoindre la conversation ?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Vous avez accepté la demande de conversation</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>Nous attendons de synchroniser la conversation à partir d'un autre appareil.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Accepter</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Refuser</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>Impossible de contacter l'interlocuteur</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>En attente de votre contact</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>Transfert entrant</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>Délai d'attente de votre contact dépassé</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Bloquer</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Remarque: une interaction créera un nouveau contact.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>ne fait pas parti de vos contacts</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Remarque: vous pouvez automatiquement accepter une invitation en lui répondant.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>Il y a {0} jours</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>il y a {0} heures</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>il y a {0} minutes</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Annulé</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>En cours</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>Il y a %d jours</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>Il y a %d heures</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>Il y a %d minutes</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>il y a une journée</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>il y a une heure</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>juste maintenant</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Échec</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Supprimer</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Réessaie</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Recherche...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>ID invalide</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Nom d'utilisateur non trouvé</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>Impossible de vérifier le nom d'utilisateur</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Schéma d'URI non supporté</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_fr_CH.ts b/translations/lrc_fr_CH.ts new file mode 100644 index 0000000000000000000000000000000000000000..92a402906d4f8e9a6bf94f5ae85b9e3780b3c209 --- /dev/null +++ b/translations/lrc_fr_CH.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="fr_CH" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Moi</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Mettre en attente</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Appel en cours</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>ERREUR</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Appel entrant</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Appel en cours</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Connexion en cours</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Recherche en cours</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Inactif</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Terminé</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Expiré</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Interlocuteur occupé</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Communication établie</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Invitation reçue</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Contact ajouté</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation>%1 a été invité(e)</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 s'est joint</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 a quitté</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation>%1 a été exclu(e)</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation>%1 a été de nouveau rajouté(e)</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation>Le Swarm a été créé</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Appel sortant</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Appel entrant</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Appel sortant manqué</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Appel entrant manqué</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Invitation acceptée</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>défaut</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Null</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Essai en cours</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Sonnerie en cours</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>En cours de transfert</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>Mis dans la file d'attente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>En cours</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>ok</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Accepté</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Choix multiples</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Définitivement déplacé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Temporairement déplacé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Utiliser un serveur délégataire</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Service alternatif</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Requête invalide</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Non authorisé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Payement nécessaire</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Interdit</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Introuvable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Méthode non permise</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>N'est pas acceptable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Authentification au serveur mandataire nécessaire</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Délai de la requête dépassé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Parti</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>L'élément demandé est trop gros</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>l'URI demandée est trop longue</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Type de média non supporté</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Schéma d'URI non supporté</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Mauvaise extension</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Extension nécessaire</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Compteur de session trop petit</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Intervalle trop court</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Temporairement non disponible</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>L'appel TSX n’existe pas</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Boucle détectée</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Trop de sauts</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Adresse incomplète</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>Ambigu</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Occupé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>La requête est terminée</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Événement incorrect</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Requête modifiée</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Requête en attente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Indéchiffrable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Erreur Interne du Serveur</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Non Implémenté</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Mauvaise passerelle</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Service indisponible</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Dépassement de délai du serveur</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Version non supportée</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Message Trop Large</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Échec de Précondition </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Occupé partout</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Appel refusé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>N'existe nul part</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>N'est pas acceptable ici</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Cacher la fenêtre de clavardage</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Faire un appel vidéo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Montrer les modules d'extension disponibles</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Faire un appel audio</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Ajouter aux conversations</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Débloquer le contact</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Envoyer</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>Options</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Faire défiler jusqu'à la fin de la conversation</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Envoyer fichier</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Ajouter un émoji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Envoyer un message vidéo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Envoyer un message vocal</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Copier pour télécharger</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>Écrire à {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>vous a envoyé une demande de conversation</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Bonjour, souhaitez-vous rejoindre la conversation ?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Vous avez accepté la demande de conversation</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>Nous attendons de synchroniser la conversation à partir d'un autre appareil.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Accepter</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Refuser</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>Impossible de contacter l'interlocuteur</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>En attente de votre contact</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>Transfert entrant</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>Délai d'attente de votre contact dépassé</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Bloquer</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Remarque: une interaction créera un nouveau contact.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>ne fait pas parti de vos contacts</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Remarque: vous pouvez automatiquement accepter une invitation en lui répondant.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>Il y a {0} jours</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>il y a {0} heures</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>il y a {0} minutes</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Annulé</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>En cours</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>Il y a %d jours</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>Il y a %d heures</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>Il y a %d minutes</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>il y a une journée</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>il y a une heure</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>juste maintenant</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Échec</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Supprimer</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Réessaie</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Recherche...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>ID invalide</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Nom d'utilisateur non trouvé</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>Impossible de vérifier le nom d'utilisateur</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Schéma d'URI non supporté</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_fr_FR.ts b/translations/lrc_fr_FR.ts new file mode 100644 index 0000000000000000000000000000000000000000..7ed34b51b996bb2dfc873a0fef24f0e1796ee5a3 --- /dev/null +++ b/translations/lrc_fr_FR.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="fr_FR" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Moi </translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Patienter</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Appel en cours</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>ERREUR</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Appel entrant</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Appel en cours</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>En cours de connexion</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Recherche en cours</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Inactif</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Terminé</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Expiré</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Interlocuteur occupé</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Communication établie</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Invitation reçue</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Contact ajouté</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation>%1 a été invité(e)</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 s'est joint</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 a quitté</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation>%1 a été exclu(e)</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation>%1 a été de nouveau rajouté(e)</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation>Le Swarm a été créé</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Appel sortant</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Appel entrant</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Appel sortant manqué</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Appel entrant manqué</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Invitation acceptée</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>défaut</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Null</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Essai en cours</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Sonnerie en cours</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>En cours de transfert</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>Mis dans la file d'attente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>En cours</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>ok</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Accepté</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Choix multiples</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Définitivement déplacé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Temporairement déplacé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Utiliser un serveur délégataire</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Service alternatif</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Requête invalide</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Non authorisé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Payement nécessaire</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Interdit</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Introuvable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Méthode non permise</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>N'est pas acceptable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Authentification au serveur mandataire nécessaire</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Délai de la requête dépassé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Parti</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>L'élément demandé est trop gros</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>l'URI demandée est trop longue</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Type de média non supporté</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Schéma d'URI non supporté</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Mauvaise extension</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Extension nécessaire</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Compteur de session trop petit</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Intervalle trop court</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Temporairement non disponible</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>L'appel TSX n’existe pas</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Boucle détectée</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Trop de sauts</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Adresse incomplète</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>Ambigu</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Occupé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>La requête est terminée</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Événement incorrect</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Requête modifiée</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Requête en attente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Indéchiffrable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Erreur Interne du Serveur</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Non Implémenté</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Mauvaise passerelle</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Service indisponible</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Dépassement de délai du serveur</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Version non supportée</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Message Trop Large</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Échec de Précondition </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Occupé partout</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Appel refusé</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>N'existe nul part</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>N'est pas acceptable ici</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Cacher la fenêtre de clavardage</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Faire un appel vidéo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Montrer les modules d'extension disponibles</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Faire un appel audio</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Ajouter aux conversations</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Débloquer le contact</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Envoyer</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>Options</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Faire défiler jusqu'à la fin de la conversation</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Envoyer le fichier</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Ajouter un émoji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Envoyer un message vidéo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Envoyer un message vocal</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Copier pour télécharger</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>Écrire à {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>vous a envoyé une demande de conversation</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Bonjour, souhaitez-vous rejoindre la conversation ?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Vous avez accepté la demande de conversation</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>Nous attendons de synchroniser la conversation à partir d'un autre appareil.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Accepter</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Refuser</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>Impossible de contacter l'interlocuteur</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>En attente de votre contact</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>Transfert entrant</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>Délai d'attente de votre contact dépassé</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Bloquer</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Remarque: une interaction créera un nouveau contact.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>ne fait pas parti de vos contacts</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Remarque: vous pouvez automatiquement accepter une invitation en lui répondant.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>Il y a {0} jours</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>il y a {0} heures</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>il y a {0} minutes</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Annulé</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>En cours</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>Il y a %d jours</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>Il y a %d heures</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>Il y a %d minutes</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>il y a une journée</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>il y a une heure</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>juste maintenant</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Échec</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Supprimer</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Réessaie</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Recherche...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>ID invalide</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Nom d'utilisateur non trouvé</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>Impossible de vérifier le nom d'utilisateur</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Schéma d'URI non supporté</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_ga.ts b/translations/lrc_ga.ts new file mode 100644 index 0000000000000000000000000000000000000000..63f21a9a9b3b40f06f6977d3f2f4d3b77592aec9 --- /dev/null +++ b/translations/lrc_ga.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="ga" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>Chláraigh %1</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>réamhshocrú</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Ceart go leor</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Comhad a sheoladh</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Cealaithe</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_gl.ts b/translations/lrc_gl.ts new file mode 100644 index 0000000000000000000000000000000000000000..03ec7079f854c6a7ae97171b4410f455b3003f8d --- /dev/null +++ b/translations/lrc_gl.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="gl" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Eu</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Agardar</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Falando</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>ERRO</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Entrante</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Chamando</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Conectando</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Buscando</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Inactiva</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Rematada</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Caducada</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Persoa ocupada</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Comunicación establecida</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Convite recibido</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Contacto engadido</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 uniuse</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Chamada saÃnte</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Chamada entrante</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Chamada sen resposta</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Chamada entrante perdida</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Convite aceptado</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>por omisión</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Null</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Intentando</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Chamando</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>Reenviando</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>Na cola</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>Progreso</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Aceptar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Aceptado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Múltiples opcións</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Movido permanentemente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Movido temporalmente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Usar Proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Servizo alternativo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Solicitude incorrecta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Non autorizado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Require pagamento</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Prohibido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Non atopado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Método non permitido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>Non aceptable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>O Proxy require autenticación</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Caducou a solicitude</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Marchou</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Entidade da solicitude demasiado longa</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>URI da petición demasiado longa</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Tipo de multimedia non soportado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Esquema URI non soportado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Extensión incorrecta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Require extensión</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Temporizador da sesión demasiado curto</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Intervalo demasiado breve</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Non dispoñible temporalmente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>Chamada TSX non existe</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Bucle detectado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Demasiados saltos</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Enderezo incompleto</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>AmbÃguo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Ocupado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Solicitude rematada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Evento incorrecto</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Solicitude actualizada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Solicitude pendente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Indescifrable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Fallo interno do servidor</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Non implementado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Pasarela incorrecta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Servizo non dispoñible</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Caducidade do servidor</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Versión non soportada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Mensaxe demasiado longa</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Fallo da precondición</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Todos ocupados</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Chamada rexeitada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>Non existe en ningures</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>Non aceptable en ningures</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Agochar a vista de conversa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Facer chamada de vÃdeo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Mostrar complementos dispoñibles</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Facer chamada de audio</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Engadir as conversas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Desbloquear contacto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Enviar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>Opcións</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Ir á última</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Enviar ficheiro</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Engadir emoji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Deixar unha mensaxe de vÃdeo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Deixar unha mensaxe de audio</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Copiar a descargas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>Escribir a {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>enviouche unha solicitude para conversar.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Ola, queres unirte á conversa?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Aceptaches a solicitude para conversar.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>Estamos agardando a que o outro dispositivo sincronice a conversa.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Aceptar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Rexeitar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>Non foi posible contactar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>Agardando polo contacto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>Transferencia entrante</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>Caducou a espera polo contacto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Bloquear</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Nota: unha interacción creará un novo contacto.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>non está nos teus contactos</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Nota: podes aceptar automáticamente este convite se envÃas unha mensaxe.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>fai {0} dÃas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>fai {0} horas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>fai {0} minutos</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Cancelado</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>SaÃnte</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>fai %d dÃas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>fai %d hora</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>fai %d minutos</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>fai un dÃa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>fai unha hora</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>xusto agora</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Fallo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Eliminar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Volta a intentar</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Buscando...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>ID non válido</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Non se atopou a usuaria</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>Non se puido establecer..</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Esquema URI incorrecto</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_gu.ts b/translations/lrc_gu.ts new file mode 100644 index 0000000000000000000000000000000000000000..5a6b496400380b7f12eaf094455fb8616c743a91 --- /dev/null +++ b/translations/lrc_gu.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="gu" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 જોડાયા</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>ડિફૉલà«àªŸ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>બરાબર</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>વાતચીતના અંત સà«àª§à«€ સà«àª•à«àª°à«‹àª² કરો</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>ફાઇલ મોકલો</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>રદ થયેલ છે</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_he.ts b/translations/lrc_he.ts new file mode 100644 index 0000000000000000000000000000000000000000..f5f6e4ddf21dee394ff5ac233ab8c299bdcd219c --- /dev/null +++ b/translations/lrc_he.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="he" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>×× ×™</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>החזקה</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>מדבר</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>שגי××”</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>× ×›× ×¡×ª</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>מתחבר</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>מחפש</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 הצטרף</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>שיחה יוצ×ת</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>שיחה × ×›× ×¡×ª</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>ברירת מחדל</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>מצלצל</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>×ישור</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>עסוק</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>להסתיר תצוגת צ׳×ט</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>בצע שיחת ויד×ו</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>בצע שיחה קולית</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>הוסף לשיחות</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>שלח</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>גלול לקצה השיחה</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>שלח קובץ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>לקבל</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>לדחות</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>חסו×</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>הערה: ××™× ×˜×¨×קציה תיצור ×יש קשר חדש.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>הערה: × ×™×ª×Ÿ לקבל ×”×–×ž× ×” זו ×וטומטית על ידי שליחת הודעה.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>מבוטל</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>×œ×¤× ×™ %d ימי×</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>×œ×¤× ×™ %d שעות</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>×œ×¤× ×™ %d דקות</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>×œ×¤× ×™ יו×</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>×œ×¤× ×™ שעה</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>כישלון</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>מחק</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>× ×¡×” שוב</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>בחיפוש...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_hi.ts b/translations/lrc_hi.ts new file mode 100644 index 0000000000000000000000000000000000000000..5147a831302eefd77b949c97ded923ecbd75ed7a --- /dev/null +++ b/translations/lrc_hi.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="hi" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 शामिल हà¥à¤</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>आउटगोइंग कॉल</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>फोन आ रहा है </translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>मिसà¥à¤¡ आउटगोइंग कॉल</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>मिसà¥à¤¡ इनकमिंग कॉल</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>डिफ़ॉलà¥à¤Ÿ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>ठीक</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>वारà¥à¤¤à¤¾à¤²à¤¾à¤ª के अंत तक सà¥à¤•à¥à¤°à¥‰à¤² करें</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>फ़ाइल à¤à¥‡à¤œà¥‡à¤‚</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>रदà¥à¤¦ किया गया</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_hi_IN.ts b/translations/lrc_hi_IN.ts new file mode 100644 index 0000000000000000000000000000000000000000..6ff62b88c0a812d90293ead69f324dd26eb3da0b --- /dev/null +++ b/translations/lrc_hi_IN.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="hi_IN" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 शामिल हà¥à¤</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>आउटगोइंग कॉल</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>फोन आ रहा है </translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>मिसà¥à¤¡ आउटगोइंग कॉल</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>मिसà¥à¤¡ इनकमिंग कॉल</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>डिफ़ॉलà¥à¤Ÿ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>ठीक</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>वारà¥à¤¤à¤¾à¤²à¤¾à¤ª के अंत तक सà¥à¤•à¥à¤°à¥‰à¤² करें</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>फ़ाइल à¤à¥‡à¤œà¥‡à¤‚</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>रदà¥à¤¦ किया गया</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_hr.ts b/translations/lrc_hr.ts new file mode 100644 index 0000000000000000000000000000000000000000..44b91ce0a51abef4bea3871bda5ddf9276eb0220 --- /dev/null +++ b/translations/lrc_hr.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="hr" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Ja</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Na Äekanje</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Razgovaram</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>GREÅ KA</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Zovem</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Spajanje</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Poziv uspostavljen</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Poziv primljen</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Kontakt dodan</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 se pridružio/la</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Odlazni poziv</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Dolazni poziv</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>PropuÅ¡teni odlazni poziv</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>PropuÅ¡teni dolazni poziv</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>zadano</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Zvoni</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>U redu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Zauzeto</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>PoÅ¡alji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Pomicanje na kraj razgovora</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>PoÅ¡alji datoteku</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Prihvati</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Odbij</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Blokiraj</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Otkazano</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>IzbriÅ¡i</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_hu.ts b/translations/lrc_hu.ts new file mode 100644 index 0000000000000000000000000000000000000000..ded80df28de472f25762febb6b697efcc11bd922 --- /dev/null +++ b/translations/lrc_hu.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="hu" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Én</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Tartás</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>HÃvásban</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>HIBA</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>BejövÅ‘</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>HÃvás</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Kapcsolódás</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Keresés</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Tétlen</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Befejezett</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>IdÅ‘túllépés</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Kapcsolat elfoglalt</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>A közlés létrejött</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>MeghÃvás megérkezett</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Kapcsolat hozzáadva</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation>%1 meghÃvást kapott a csatlakozásra</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 csatlakozott</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 kilépett</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation>%1 el lett távolÃtva</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation>%1 újra hozzáadva</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation>Rajcsoport létrehozva</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>KimenÅ‘ hÃvás</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>BejövÅ‘ hÃvás</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Nem fogadott kimenÅ‘ hÃvás</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Nem fogadott bejövÅ‘ hÃvás</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>MeghÃvás elfogadott</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>alapértelmezett</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Semmis</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Próbálkozik…</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Csörögni</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>HÃvásátirányÃtás…</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>Sorban áll</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>Készültségi fok</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Rendben</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Elfogadott</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Több választási lehetÅ‘ség</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Véglegesen áthelyezve</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Ãtmenetileg áthelyezve</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Meghatalmazás használata</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>AlternatÃv szolgáltatás</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Rossz kérés</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Jogtalan</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Fizetés szükséges</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Tiltott</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Nem található</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Nem megengedett módszer</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>Elfogadhatatlan</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Meghatalmazott hitelesÃtés szükséges</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>IdÅ‘t kér</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Elmúlt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>A kérelem entitása túl nagy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>URI kérés túl hosszú</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Nem támogatott médiatÃpus</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Nem támogatott URI rendszer</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Hibás bÅ‘vÃtmény</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>BÅ‘vÃtmény szükséges</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>A munkamenet idÅ‘zÃtÅ‘je túl rövid</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Túl rövid idÅ‘intervallum</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Ideiglenesen nem elérhetÅ‘</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>A TSX nem létezik</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Érzékelt hurok</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Túl sok komló</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>A cÃm hiányos</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>Kétértelmű</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Foglalt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Kérés megszűnt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Rossz esemény</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>A kérelem frissÃtése megtörtént</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>A kérelem függÅ‘ben</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Megfejthetetlen</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>BelsÅ‘ kiszolgálóhiba</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Nincs végrehajtott</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Rossz átjáró</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>A szolgáltatás nem elérhetÅ‘</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Kiszolgáló idÅ‘túllépése</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Verzió nem támogatott</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Ãœzenet túl hosszú</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>ElÅ‘feltétel meghiúsulása</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Mindenhol elfoglalt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>HÃvás visszautasÃtott</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>Sehol nem létezik</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>Bárhol nem elfogadható</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Csevegés elrejtése</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>VideohÃvás</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>ElérhetÅ‘ beépülÅ‘ modulok megjelenÃtése</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>HanghÃvás</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Beszélgetések hozzáadása</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Kapcsolat letiltás feloldása</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Küldés</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>BeállÃtások</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Görgetés a beszélgetés végére</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Fájl küldése</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Hangulatjel hozzáadása</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Videoüzenet hagyása</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Hangüzenet hagyása</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Másolás a letöltésekhez</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>Ãrj a következÅ‘(k)nek: {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>beszélgetési kérelmet küldött Önnek.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Helló, csatlakozni szeretne a beszélgetéshez?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Elfogadta a beszélgetési kérelmet.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>Várunk egy másik eszközre, hogy összehangolja a beszélgetést. </translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Elfogadás</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>ElutasÃtás</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>Nem sikerült kapcsolatba lépni</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>Várakozás a kapcsolatfelvételre</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>BejövÅ‘ fájlküldés</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>IdÅ‘túllépés várt a kapcsolattartásra</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Letiltás</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Megjegyzés: az együttműködés új kapcsolatot hoz létre.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>nincs a kapcsolataiban</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Megjegyzés: az üzenet elküldésével önműködÅ‘en elfogadhatja ezt a meghÃvást.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>{0} napja</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>{0} órája</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>{0} perce</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>MegszakÃtva</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>Folyamatban lévÅ‘</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>%d napja</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>%d órája</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>%d perce</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>egy napja</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>egy órája</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>most</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Hiba</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Törlés</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Újra</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Keresés…</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>Érvénytelen azonosÃtó</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Felhasználónév nem található</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>Betekintés sikertelen…</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Rossz URI rendszer</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_id.ts b/translations/lrc_id.ts new file mode 100644 index 0000000000000000000000000000000000000000..8d0ab763a22ca50781084553f85b8bcb7990bedd --- /dev/null +++ b/translations/lrc_id.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="id" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Saya</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Tahan</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Bicara</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Panggilan masuk</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Menghubungkan</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Mencari</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Undangan diterima</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Kontak ditambahkan</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 bergabung</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Panggilan keluar</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Panggilan masuk</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Panggilan keluar tidak terjawab</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Panggilan masuk tidak terjawab</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>bawaan</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Berdering</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Oke</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Sibuk</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Kirim</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Gulir ke akhir percakapan</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Kirim berkas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Terima</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Tolak</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Blokir</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Dibatalkan</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Hapus</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_ig.ts b/translations/lrc_ig.ts new file mode 100644 index 0000000000000000000000000000000000000000..f3a8e2c45af1ec0e1331a717a5f1326cbbbcd23c --- /dev/null +++ b/translations/lrc_ig.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="ig" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 sonyere</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>eburupụta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Dị-mma</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Zie</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Zipu faịlụ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>A kagbuola ihe omume ahụ.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_it.ts b/translations/lrc_it.ts new file mode 100644 index 0000000000000000000000000000000000000000..73290cc3ab31f1a1863018c7023a1796b5d5f12d --- /dev/null +++ b/translations/lrc_it.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="it" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Io</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Pausa</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Parlando</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>ERRORE</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>In arrivo</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Stai chiamando</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Connessione in corso </translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Ricerca in corso</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Inattivo</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Completato</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Tempo scaduto</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Occupato</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Connessione stabilita</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Invito ricevuto</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Contatto aggiunto</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation>%1 è stato invitato a partecipare</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 si è unito</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 è uscito</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation>%1 è stato espulso</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation>%1 è stato riammesso</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation>Gruppo creato</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Chiamata in uscita</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Chiamata in arrivo</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Chiamata in uscita persa</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Chiamata in arrivo persa</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Invito accettato</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>predefinito</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Null</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Tentativo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Squilla</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>In inoltro</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>In coda</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>In corso</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>OK</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Accettato</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Scelta multipla</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Spostato definitivamente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Spostato temporaneamente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Usa proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Servizio alternativo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Richiesta errata</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Non autorizzato</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Pagamento richiesto</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Vietato</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Non trovato</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Metodo non permesso</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>Non accettabile</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Richiesta autenticazione proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Tempo scaduto</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Assente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Entità richiesta troppo grande</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>l'URI richiesto è troppo lungo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Tipo di Media non accettato</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Schema URI non accettato</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Estensione errata</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Estensione richiesta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Tempo di sessione troppo breve</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Intervallo troppo breve</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Temporaneamente non disponibile</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>Chiamata TSX non esiste</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Rilevato loop</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Troppi Hop</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Indirizzo incompleto</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>Ambiguo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Occupato</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Richiesta terminata</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Evento negativo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Richiesta aggiornata</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Richiesta in corso</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Indecifrabile</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Errore interno del server</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Non implementato</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Gateway incorretto</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Servizio non disponibile</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Tempo scaduto per il server</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Versione non supportata</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Messaggio troppo grande</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Fallimento della precondizione</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Occupato ovunque</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Chiamata rifiutata</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>Non esiste da nessuna parte</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>Non accettabile ovunque</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Nascondi chat</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Effettua videochiamata</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Mostra i plugin disponibili</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Effettua chiamata vocale</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Aggiungi alle conversazioni</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Sblocca contatto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Invia</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>Opzioni</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Vai alla fine della conversazione</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Invia file</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Aggiungi emoji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Registra videomessaggio</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Registra messaggio vocale</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Copia per scaricare</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>Scrivi a {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>ti ha inviato una richiesta di conversazione.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Ciao, vuoi partecipare alla conversazione?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Hai accettato la richiesta di conversazione.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>In attesa che altri dispositivi sincronizzino la conversazione.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Accetta</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Rifiuta</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>Impossibile prendere contatto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>In attesa di contatto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>Trasferimento in entrata</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>Tempo scaduto in attesa di contatto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Blocca</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Nota: un'interazione creerà un nuovo contatto.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>non è nei tuoi contatti</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Nota: puoi accettare automaticamente questo invito inviando un messaggio.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>{0} giorni fa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>{0} ore fa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>{0} minuti fa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Annullato</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>In corso</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>%d giorni fa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>%d ore fa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>%d minuti fa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>un giorno fa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>un'ora fa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>ora</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Fallimento</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Elimina</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Riprova</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Ricerca in corso...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>ID non valido</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Nome utente non trovato</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>Impossibile cercare…</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Schema URI errato</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_it_IT.ts b/translations/lrc_it_IT.ts new file mode 100644 index 0000000000000000000000000000000000000000..545a90cd7e155ada86285566012815449ffd03e2 --- /dev/null +++ b/translations/lrc_it_IT.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="it_IT" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Io</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Pausa</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Parla</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>ERRORE</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>In arrivo</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Stai chiamando</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Collegamento</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Ricerca</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Inattivo</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Finito</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Tempo scaduto</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Occupato</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Connessione stabilita</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Invito ricevuto</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Contatto aggiunto</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation>%1 è stato invitato a partecipare</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 si è unito</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 è uscito</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation>%1 è stato espulso</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation>%1 è stato riammesso</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation>Gruppo creato</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Chiamata in uscita</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Chiamata in arrivo</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Chiamata in uscita persa</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Chiamata in arrivo persa</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Invito accettato</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>predefinito</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Null</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Tentativo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Squilla</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>In inoltro</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>In coda</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>In corso</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>OK</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Accettato</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Scelta multipla</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Spostato definitivamente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Spostato temporaneamente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Usa proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Servizio alternativo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Richiesta errata</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Non autorizzato</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Pagamento richiesto</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Vietato</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Non trovato</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Metodo non permesso</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>Non accettabile</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Richiesta autenticazione proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Tempo scaduto</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Assente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Entità richiesta troppo grande</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>l'URI richiesto è troppo lungo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Tipo di Media non supportato</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Schema URI non supportato</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Estensione errata</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Estensione obbligatoria</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Timer di sessione troppo breve</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Intervallo troppo breve</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Temporaneamente non disponibile</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>Chiamata TSX non esiste</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Rilevato loop</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Troppi Hop</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Indirizzo incompleto</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>Ambiguo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Occupato</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Richiesta terminata</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Evento negativo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Richiesta aggiornata</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Richiesta in corso</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Indecifrabile</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Errore interno del server</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Non implementato</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Gateway incorretto</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Servizio non disponibile</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Tempo scaduto per il server</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Versione non supportata</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Messaggio troppo grande</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Fallimento della precondizione</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Occupato ovunque</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Chiamata rifiutata</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>Non esiste da nessuna parte</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>Non accettabile ovunque</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Nascondi chat</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Effettua videochiamata</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Mostra i plugin disponibili</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Effettua chiamata vocale</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Aggiungi alle conversazioni</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Contatto vietato</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Invia</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>Opzioni</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Vai alla fine della conversazione</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Invia file</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Aggiungi emoji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Registra videomessaggio</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Registra messaggio vocale</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Copia per scaricare</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>Scrivi a {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>ti ha inviato una richiesta di conversazione.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Ciao, vuoi partecipare alla conversazione?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Hai accettato la richiesta di conversazione.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>In attesa che altri dispositivi sincronizzino la conversazione.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Accetta</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Rifiuta</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>Impossibile prendere contatto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>In attesa di contatto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>Trasferimento in entrata</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>Tempo scaduto in attesa di contatto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Blocca</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Nota: un'interazione creerà un nuovo contatto.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>non è nei tuoi contatti</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Nota: puoi accettare automaticamente questo invito inviando un messaggio.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>{0} giorni fa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>{0} ore fa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>{0} minuti fa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Annullato</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>In corso</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>%d giorni fa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>%d ore fa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>%d minuti fa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>un giorno fa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>un'ora fa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>proprio adesso</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Fallito</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Elimina</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Riprova</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Ricerca...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>ID non valido</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Nome utente non trovato</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>Impossibile cercare…</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Schema URI errato</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_ja.ts b/translations/lrc_ja.ts new file mode 100644 index 0000000000000000000000000000000000000000..557a05c4e492932089c7e2c712a12edefa6c9538 --- /dev/null +++ b/translations/lrc_ja.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="ja" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>自分</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>ä¿ç•™</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>通話ä¸</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>エラー</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>ç€ä¿¡</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>発信ä¸</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>接続ä¸</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>検索ä¸</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>通話終了</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>タイムアウト</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>ピアビジー</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>通信を確立ã—ã¾ã—ãŸ</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>招待をå—ä¿¡ã—ã¾ã—ãŸ</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>é€£çµ¡å…ˆã‚’è¿½åŠ ã—ã¾ã—ãŸ</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 ã•ã‚“ãŒå‚åŠ ã—ã¾ã—ãŸ</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>発信</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>ç€ä¿¡</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>ä¸åœ¨ç™ºä¿¡</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>ä¸åœ¨ç€ä¿¡</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>招待をå—ã‘入れã¾ã—ãŸ</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>既定</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>ãªã—</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>試行ä¸</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>ç€ä¿¡ä¸</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>転é€ä¸</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>å¾…æ©Ÿä¸</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>進行状æ³</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>ã‚ã‹ã£ãŸ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>å—諾済ã¿</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>複数ã®é¸æŠžè‚¢</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>完全ã«ç§»å‹•ã—ã¾ã—ãŸ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>一時的ã«ç§»å‹•ã—ã¾ã—ãŸ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>プãƒã‚シを使ã†</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>代替サービス</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>ä¸æ£ãªãƒªã‚¯ã‚¨ã‚¹ãƒˆ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>未èªè¨¼</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>支払ã„ãŒå¿…è¦</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>ç¦æ¢</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>見ã¤ã‹ã‚Šã¾ã›ã‚“</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>許å¯ã•ã‚Œã¦ã„ãªã„æ–¹å¼</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>å—ã‘入れä¸å¯</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>プãƒã‚シーèªè¨¼ãŒå¿…è¦</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>リクエストタイムアウト</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>退去</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>リクエストサイズãŒå¤§ãã™ãŽã¾ã™</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>リクエストURLãŒé•·ã™ãŽã¾ã™</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>サãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ãªã„メディア形å¼</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>サãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ãªã„URLスã‚ーム</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>ä¸æ£ãªæ‹¡å¼µå</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>æ‹¡å¼µåãŒå¿…è¦</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>セッションタイマーãŒçŸã™ãŽã¾ã™</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>é–“éš”ãŒçŸã™ãŽã¾ã™</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>一時的ã«åˆ©ç”¨ã§ãã¾ã›ã‚“</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>Call TSXãŒå˜åœ¨ã—ã¾ã›ã‚“</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>ループãŒæ¤œå‡ºã•ã‚Œã¾ã—ãŸ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>ホップ数ãŒå¤šã™ãŽã¾ã™</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>アドレスãŒä¸å®Œå…¨ã§ã™</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>ä¸æ˜Žçž</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>通話ä¸</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>リクエストãŒå¼·åˆ¶çµ‚了ã•ã‚Œã¾ã—ãŸ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>ä¸æ£ãªã‚¤ãƒ™ãƒ³ãƒˆ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>リクエストを更新ã—ã¾ã—ãŸ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>リクエストãŒä¿ç•™ä¸ã§ã™</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>復å·ã§ãã¾ã›ã‚“</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>内部サーãƒãƒ¼ã‚¨ãƒ©ãƒ¼</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>未実装ã§ã™</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>ä¸æ£ãªã‚²ãƒ¼ãƒˆã‚¦ã‚§ã‚¤</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>サービス利用ä¸å¯</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>サーãƒãƒ¼ã‚¿ã‚¤ãƒ アウト</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>サãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ãªã„ãƒãƒ¼ã‚¸ãƒ§ãƒ³</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>メッセージãŒå¤§ãã™ãŽã¾ã™</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>通話ãŒæ‹’å¦ã•ã‚Œã¾ã—ãŸ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>ã©ã“ã«ã‚‚å˜åœ¨ã—ã¾ã›ã‚“</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>ãƒãƒ£ãƒƒãƒˆã‚’éš ã™</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>ビデオ通話を開始</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>音声通話を開始</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>会話ã«è¿½åŠ </translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>é€ä¿¡</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>会話ã®æœ€å¾Œã¾ã§ã‚¹ã‚¯ãƒãƒ¼ãƒ«</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>ファイルã®é€ä¿¡</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>å—ã‘入れ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>æ‹’å¦</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>ブãƒãƒƒã‚¯</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>通知: メッセージをé€ä¿¡ã™ã‚‹ã¨ã€è‡ªå‹•çš„ã«ã“ã®æ‹›å¾…ã‚’å—ã‘入れã¾ã™ã€‚</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>ã‚ャンセルã—ã¾ã—ãŸ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>%d æ—¥å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>%d 時間å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>%d 分å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>1 æ—¥å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>1 時間å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>ã¡ã‚‡ã†ã©ä»Š</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>削除</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>å†è©¦è¡Œ</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>検索ä¸â€¦</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>ä¸æ£ãªID</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>見ã¤ã‘られã¾ã›ã‚“ã§ã—ãŸ...</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>ä¸æ£ãªURLスã‚ーム</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_kk.ts b/translations/lrc_kk.ts new file mode 100644 index 0000000000000000000000000000000000000000..706b079f59bbea28e4df75b6d84db3b9fca5cfca --- /dev/null +++ b/translations/lrc_kk.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="kk" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 қоÑылды</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>әдепкі</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Жарайды</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Файл жіберу</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Ð‘Ð°Ñ Ñ‚Ð°Ñ€Ñ‚Ñ‹Ð»Ð´Ñ‹</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_kn.ts b/translations/lrc_kn.ts new file mode 100644 index 0000000000000000000000000000000000000000..8aba02224ed5a53c8c98d847cfcb9a9e984d46e2 --- /dev/null +++ b/translations/lrc_kn.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="kn" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 ಸೇರಿದà³à²¦à²¾à²°à³†</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>ಡೀಫಾಲà³à²Ÿà³</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>ಸರಿ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>ಸಂà²à²¾à²·à²£à³†à²¯ ಕೊನೆಯ à²à²¾à²—ಕà³à²•à³† ಸà³à²•à³à²°à²¾à²²à³ ಮಾಡಿ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>ಫೈಲೠಕಳà³à²¹à²¿à²¸à³</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>ರದà³à²¦à³à²—ೊಳಿಸಲಾಗಿದೆ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_ko.ts b/translations/lrc_ko.ts new file mode 100644 index 0000000000000000000000000000000000000000..3c9321d1a0aa2d58d582591f81e8ba2e62063e6d --- /dev/null +++ b/translations/lrc_ko.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="ko" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>통화 중</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 ë‹˜ì´ ì°¸ê°€í–ˆìŠµë‹ˆë‹¤</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>기본값</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>확ì¸</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>ëŒ€í™”ì˜ ë으로 스í¬ë¡¤</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>íŒŒì¼ ë³´ë‚´ê¸°</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>수ë½</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>취소ë¨</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_ko_KR.ts b/translations/lrc_ko_KR.ts new file mode 100644 index 0000000000000000000000000000000000000000..f5c0f4f91cfdddf12327e7eb655febce500d609e --- /dev/null +++ b/translations/lrc_ko_KR.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="ko_KR" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>통화 중</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 ë‹˜ì´ ì°¸ê°€í–ˆìŠµë‹ˆë‹¤</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>기본값</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>확ì¸</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>ëŒ€í™”ì˜ ë으로 스í¬ë¡¤</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>íŒŒì¼ ë³´ë‚´ê¸°</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>수ë½</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>취소ë¨</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_lt.ts b/translations/lrc_lt.ts new file mode 100644 index 0000000000000000000000000000000000000000..ab7e76c433e234ceec484f61e12fae0b1a31e13a --- /dev/null +++ b/translations/lrc_lt.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="lt" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>AÅ¡</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Užlaikyta</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Kalbama</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>KLAIDA</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Gaunamasis</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Skambinama</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Sujungiama</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>IeÅ¡koma</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Užbaigta</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>RyÅ¡ys užmegztas</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Gautas pakvietimas</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Adresatas pridÄ—tas</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 prisijungÄ—</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>IÅ¡siunÄiamasis skambutis</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Gaunamasis skambutis</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Praleistas gaunamasis skambutis</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Pakvietimas priimtas</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>numatytasis</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Bandoma</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Skambina</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Gerai</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Bloga Užklausa</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Neleidžiama</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Nerasta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Užklausos laikas baigÄ—si</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Nepalaikoma URI schema</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Aptiktas ciklas</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Nepilnas adresas</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Užimta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Blogas įvykis</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>VidinÄ— Serverio Klaida</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Neįgyvendinta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Blogas Tinklų Sietuvas</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Versija nÄ—ra palaikoma</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>SlÄ—pti pokalbio rodinį</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>PradÄ—ti vaizdo skambutį</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>PradÄ—ti garso skambutį</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Siųsti</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Slinkite į pokalbio pabaigÄ…</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Siųsti failÄ…</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Priimti</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Atmesti</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Užblokuoti</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Pastaba: sÄ…veika sukurs naujÄ… adresatÄ….</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Pastaba: galite automatiÅ¡kai priimti šį pakvietimÄ… iÅ¡siųsdami žinutÄ™.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Atsisakyta</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>prieÅ¡ %d d.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>prieÅ¡ %d val.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>prieÅ¡ %d min.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>prieÅ¡ vienÄ… dienÄ…</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>prieÅ¡ vienÄ… valandÄ…</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>kÄ… tik</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>NesÄ—kmÄ—</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>IÅ¡trinti</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>IeÅ¡koma…</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>Neteisingas ID</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Bloga URI schema</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_ml.ts b/translations/lrc_ml.ts new file mode 100644 index 0000000000000000000000000000000000000000..6834ba3e993b42f51123e6e200ec3e6cf180e19d --- /dev/null +++ b/translations/lrc_ml.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="ml" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 ചേർനàµà´¨àµ</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1, വിടàµà´Ÿàµà´ªàµ‹à´¯à´¿</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>ഡിഫോൾടàµà´Ÿàµ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>ശരി</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>സംà´à´¾à´·à´£à´¤àµà´¤à´¿à´¨àµâ€à´±àµ† അവസാനതàµà´¤à´¿à´²àµ‡à´•àµà´•àµ à´¸àµâ€Œà´•àµà´°àµ‹àµ¾ ചെയàµà´¯àµà´•</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>ഫയൽ അയയàµà´•àµà´•àµà´•</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>റദàµà´¦à´¾à´•àµà´•à´¿</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_mn_MN.ts b/translations/lrc_mn_MN.ts new file mode 100644 index 0000000000000000000000000000000000000000..aa793ed54a7ac02e36cc658cf42670de2c8617a5 --- /dev/null +++ b/translations/lrc_mn_MN.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="mn_MN" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 нÑгдлÑÑ</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 гарÑан</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>өгөгдмөл</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>ЗүгÑÑÑ€</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Файл илгÑÑÑ…</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Цуцаллаа</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_mr.ts b/translations/lrc_mr.ts new file mode 100644 index 0000000000000000000000000000000000000000..0c0449775b87c646ad21f53c068100fab48e84b1 --- /dev/null +++ b/translations/lrc_mr.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="mr" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 सामील à¤à¤¾à¤²à¥‡</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 बाहेर पडले</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>डिफॉलà¥à¤Ÿ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>ठीक</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>संà¤à¤¾à¤·à¤£ संपवणà¥â€à¤¯à¤¾à¤¸à¤¾à¤ ी सà¥â€à¤•à¥à¤°à¥‹à¤² करा</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>फाइल पाठवा</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>रदà¥à¤¦ केले</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_ms.ts b/translations/lrc_ms.ts new file mode 100644 index 0000000000000000000000000000000000000000..3abe89335b141bcd3c67c4bf910cbf1d60b3e42f --- /dev/null +++ b/translations/lrc_ms.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="ms" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Saya</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Tangguh</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Bercakap</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>GAGAL</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Memanggil</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Menyambung</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Komunikasi bersambung</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 telah menyertai</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 telah keluar</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Panggilan keluar</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Panggilan masuk</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>lalai</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Berdering</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Masa permintaan tamat</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Sibuk</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Hantar fail</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Terima</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Dibatalkan</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Hapus</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_nb.ts b/translations/lrc_nb.ts new file mode 100644 index 0000000000000000000000000000000000000000..439ed9ea2737b12a58050361c304cc815d499f07 --- /dev/null +++ b/translations/lrc_nb.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="nb" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Meg</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Parker</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Snakker</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>FEIL</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Innkommende</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Kaller opp</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Kobler opp</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Søker</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Uaktiv</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Fullført</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Tidsutløp</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Motpart opptatt</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Kommunikasjon etablert</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Invitasjon mottatt</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Kontakt lagt til</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 ble med</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 forlot</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>UtgÃ¥ende samtale</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Innkommende samtale</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Tapt utgÃ¥ende anrop</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Tapt innkommende anrop</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Invitasjon godtatt</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>standard</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Null</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Prøver</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Ringer</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>Blir videresendt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>I kø</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>Framdrift</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>OK</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Godkjent</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Flere valg</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Flyttet permanent</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Flyttet midlertidig</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Bruk mellomtjener</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Alternativ tjeneste</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>DÃ¥rlig forespørsel</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Uautorisert</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Betaling kreves</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Forbudt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Ikke funnet</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Metode ikke tillatt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>Ikke akseptabelt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Proxy-godkjenning er pÃ¥krevd</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Tidsgrense for henvendelse</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Borte</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Enhetsforespørsel for stor</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>URI forespørsel for lang</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Media type ikke støttet</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>URI-ordning støttes ikke</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Utvidelse ødelagt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Utvidelse obligatorisk</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Øktur for liten</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Intervall for kort</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Midlertidig utilgjengelig</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>TSX samtale eksisterer ikke</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Løkke oppdaget</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>For mange hopp</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Ufullstendig adresse</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>Tvetydig</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Opptatt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Forespørsel avsluttet</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Handling feilet</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Forespørsel oppdatert</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Forespørsel venter</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Ugjenkjennelig</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Intern tjenerfeil</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Ikke implementert</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Feil pÃ¥ mellomtjener</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Tjeneste utilgjengelig</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Tidsavbrudd tjener</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Versjon ikke støttet</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Melding for stor</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Forutsetning feilet</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Opptatt overalt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Samtale avslÃ¥tt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>Eksisterer ingen steder</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>Aksepteres ingen steder</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Skjul sludrevisning</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Opprett videosamtale</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Vis tilgjengelige utvidelser</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Opprett talesamtale</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Legg til i samtaler</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Urban kontakt</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Send</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>Alternativer</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Bla til slutten av samtalen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Send fil</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Legg til emoji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Legg igjen videomelding</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Legg igjen samtalemelding</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Kopier til nedlastninger</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>Skriv til {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>har sendt deg en samtaleforespørsel</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Hei, har du lyst til Ã¥ bli med i samtalen?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Du har takket ja til samtaleforespørselen.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>Vi venter pÃ¥ at en annen enhet skal synkronisere samtalen.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Aksepter</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>AvslÃ¥</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>Kan ikke ta kontakt</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>Venter pÃ¥ kontakt</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>Innkommende overføring</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>Tidsavbrudd ventet pÃ¥ kontakt</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Blokker</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Merk at interaksjon vil opprette en ny kontakt.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>er ikke i dine kontakter</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Merk deg: Ved Ã¥ sende en melding takker du automatisk ja til denne invitasjonen.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>{0} dager siden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>{0} timer siden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>{0} minutter siden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Avbrutt</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>PÃ¥gÃ¥ende</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>%d dager siden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>%d timer siden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>%d minutter siden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>i gÃ¥r</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>en time siden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>akkurat nÃ¥</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Mislyktes</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Slett</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Forsøk igjen</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Søker...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>Ugyldig ID</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Fant ikke brukernavnet</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>Kunne ikke søke opp...</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Ukjent URI-type</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_ne.ts b/translations/lrc_ne.ts new file mode 100644 index 0000000000000000000000000000000000000000..da38bff4d8a728c81f606c713d22700156bf4327 --- /dev/null +++ b/translations/lrc_ne.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="ne" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 सामेल à¤à¤à¤•à¥‹ छ</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 बाà¤à¤•à¥€ छ</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>पूरà¥à¤µà¤¨à¤¿à¤°à¥à¤§à¤¾à¤°à¤¿à¤¤</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>ठीक छ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>फाइलहरू पठाउनà¥à¤¹à¥‹à¤¸à¥</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>रदà¥à¤¦ गरियो</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_nl.ts b/translations/lrc_nl.ts new file mode 100644 index 0000000000000000000000000000000000000000..aca862ac1a26179f851c093346e3de0c225944fb --- /dev/null +++ b/translations/lrc_nl.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="nl" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Ik</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>In wacht zetten</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Praten</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>FOUT</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Inkomend</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Bellen</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Verbinden</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Zoeken</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Inactief</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Beëindigd</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Time-out</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Peer is bezet</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Communicatie tot stand gebracht</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Uitnodiging ontvangen</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Contact toegevoegd</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 neemt deel</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Uitgaande oproep</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Inkomende oproep</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Gemiste uitgaande oproep</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Gemiste inkomende oproep</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Uitnodiging geaccepteerd</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>standaard</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Null</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Poging</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Gaat over</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>Bezig met doorschakelen</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>In wachtrij</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>Voortgang</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>In orde</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Geaccepteerd</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Meerdere mogelijkheden</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Permanent verplaatst</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Tijdelijk verplaatst</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Proxy gebruiken</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Alternatieve dienst</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Slecht verzoek</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Niet geautoriseerd</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Betaling vereist</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Verboden</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Niet gevonden</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Methode niet toegestaan</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>Niet acceptabel</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Proxy-authenticatie vereist</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Time-out aanvragen</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Weg</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Verzoeksentiteit te groot</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>Verzoeks-URI te lang</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Niet-ondersteund mediatype</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Niet-ondersteund URI-schema</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Slechte extensie</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Extensie vereist</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Sessietimer te klein</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Interval te kort</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Tijdelijk niet beschikbaar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>Oproep-TSX bestaat niet</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Lus gedetecteerd</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Te veel sprongen</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Onvolledig adres</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>Ambigu</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Bezet</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Verzoek beëindigd</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Slechte gebeurtenis</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Verzoek bijgewerkt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Verzoek in afwachting</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Onleesbaar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Interne serverfout</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Niet geïmplementeerd</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Slechte gateway</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Dienst niet beschikbaar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Servertime-out</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Versie niet ondersteund</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Bericht te groot</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Pre-voorwaardefout</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Overal bezet</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Oproep geweigerd</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>Bestaat nergens</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>Nergens acceptabel</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Gespreksweergave verbergen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Video-oproep plaatsen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Audio-oproep plaatsen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Toevoegen aan gesprekken</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Contact ontbannen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Versturen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Naar het einde van het gesprek schuiven</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Bestand verzenden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Accepteren</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Afwijzen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Blokkeren</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Let op: een interactie zal een nieuw contact aanmaken.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Let op: u kunt deze uitnodiging automatisch accepteren door een bericht te sturen.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Geannuleerd</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>%d dagen geleden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>%d uur geleden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>%d minuten geleden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>een dag geleden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>een uur geleden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>zonet</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Fout</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Verwijderen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Opnieuw proberen</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Bezig met zoeken…</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>Ongeldig ID</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Verkeerd URI-schema</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_nl_BE.ts b/translations/lrc_nl_BE.ts new file mode 100644 index 0000000000000000000000000000000000000000..a70f4f57cb291912eda3296e7f2cb759c8add9f0 --- /dev/null +++ b/translations/lrc_nl_BE.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="nl_BE" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Ik</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>In wacht zetten</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Praten</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>FOUT</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Inkomend</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Bellen</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Verbinden</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Zoeken</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Inactief</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Beëindigd</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Time-out</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Peer is bezig</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Communicatie tot stand gebracht</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Uitnodiging ontvangen</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Contact toegevoegd</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 neemt deel</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Uitgaande oproep</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Inkomende oproep</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Gemiste uitgaande oproep</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Gemiste inkomende oproep</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Uitnodiging aanvaard</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>standaard</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Null</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Poging</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Gaat over</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>Bezig met doorschakelen</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>In wachtrij</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>Voortgang</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>In orde</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Aanvaard</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Meerdere mogelijkheden</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Voorgoed verplaatst</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Tijdelijk verplaatst</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Proxy gebruiken</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Alternatieve dienst</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Slecht verzoek</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Ongeautoriseerd</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Betaling vereist</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Verboden</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Niet gevonden</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Methode niet toegelaten</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>Onaanvaardbaar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Proxy-authentificatie vereist</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Time-out aanvragen</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Weg</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Verzoeksentiteit te groot</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>Verzoeks-URI te lang</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Onondersteund mediatype</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Onondersteund URI-schema</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Slechte extensie</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Extensie vereist</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Sessietimer te klein</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Interval te kort</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Tijdelijk onbeschikbaar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>Oproeps-TSX bestaat niet</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Lus gedetecteerd</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Te veel sprongen</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Onvolledig adres</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>Ambigu</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Bezig</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Verzoek beëindigd</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Slechte gebeurtenis</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Verzoek bijgewerkt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Verzoek in afwachting</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Onontcijferbaar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Interne serverfout</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Niet geïmplementeerd</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Slechte gateway</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Dienst onbeschikbaar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Servertime-out</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Versie niet ondersteund</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Bericht te groot</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Pre-voorwaardefout</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Overal bezig</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Oproep geweigerd</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>Bestaat nergens</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>Nergens aanvaardbaar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Gespreksweergave verbergen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Video-oproep plaatsen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Audio-oproep plaatsen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Toevoegen aan gesprekken</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Contact ontbannen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Versturen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Naar het einde van het gesprek schuiven</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Bestand verzenden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Aanvaarden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Afwijzen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Blokkeren</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Let op: een interactie zal een nieuw contact aanmaken.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Let op: u kunt deze uitnodiging automatisch aanvaarden door een bericht te sturen.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Geannuleerd</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>%d dagen geleden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>%d uur geleden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>%d minuten geleden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>een dag geleden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>een uur geleden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>Nu net</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Fout</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Verwijderen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Herproberen</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Bezig met zoeken…</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>Ongeldige ID</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Verkeerd URI-schema</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_nl_NL.ts b/translations/lrc_nl_NL.ts new file mode 100644 index 0000000000000000000000000000000000000000..2bdd412e568fd325cd57e7980bae4e0a6808edc3 --- /dev/null +++ b/translations/lrc_nl_NL.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="nl_NL" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Ik</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>In wacht zetten</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Praten</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>FOUT</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Inkomend</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Bellen</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Verbinden</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Zoeken</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Inactief</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Beëindigd</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Time-out</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Peer is bezig</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Communicatie tot stand gebracht</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Uitnodiging ontvangen</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Contact toegevoegd</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 neemt deel</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Uitgaande oproep</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Inkomende oproep</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Gemiste uitgaande oproep</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Gemiste inkomende oproep</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Uitnodiging aanvaard</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>standaard</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Null</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Poging</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Gaat over</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>Bezig met doorschakelen</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>In wachtrij</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>Voortgang</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>In orde</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Aanvaard</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Meerdere mogelijkheden</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Voorgoed verplaatst</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Tijdelijk verplaatst</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Proxy gebruiken</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Alternatieve dienst</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Slecht verzoek</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Ongeautoriseerd</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Betaling vereist</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Verboden</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Niet gevonden</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Methode niet toegelaten</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>Onaanvaardbaar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Proxy-authentificatie vereist</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Time-out aanvragen</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Weg</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Verzoeksentiteit te groot</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>Verzoeks-URI te lang</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Onondersteund mediatype</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Onondersteund URI-schema</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Slechte extensie</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Extensie vereist</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Sessietimer te klein</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Interval te kort</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Tijdelijk onbeschikbaar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>Oproeps-TSX bestaat niet</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Lus gedetecteerd</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Te veel sprongen</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Onvolledig adres</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>Ambigu</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Bezet</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Verzoek beëindigd</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Slechte gebeurtenis</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Verzoek bijgewerkt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Verzoek in afwachting</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Onontcijferbaar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Interne serverfout</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Niet geïmplementeerd</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Slechte gateway</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Dienst onbeschikbaar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Servertime-out</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Versie niet ondersteund</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Bericht te groot</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Pre-voorwaardefout</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Overal bezig</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Oproep geweigerd</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>Bestaat nergens</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>Nergens aanvaardbaar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Gespreksweergave verbergen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Video-oproep plaatsen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Audio-oproep plaatsen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Toevoegen aan gesprekken</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Contact ontbannen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Versturen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Naar het einde van het gesprek schuiven</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Bestand verzenden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Aanvaarden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Afwijzen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Blokkeren</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Let op: een interactie zal een nieuw contact aanmaken.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Let op: u kunt deze uitnodiging automatisch aanvaarden door een bericht te sturen.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Geannuleerd</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>%d dagen geleden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>%d uur geleden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>%d minuten geleden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>een dag geleden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>een uur geleden</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>Nu net</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Fout</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Verwijderen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Opnieuw proberen</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Bezig met zoeken…</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>Ongeldige ID</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Verkeerd URI-schema</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_nn.ts b/translations/lrc_nn.ts new file mode 100644 index 0000000000000000000000000000000000000000..8d28671bb7ce64b070c7088f985236fffcb31727 --- /dev/null +++ b/translations/lrc_nn.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="nn" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 blei med</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 forlét</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>misligholde</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Bla til slutten av samtalen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Sende fil</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Avbrutt</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_oc.ts b/translations/lrc_oc.ts new file mode 100644 index 0000000000000000000000000000000000000000..ff2cf1f20824822a23dcdc6c34787adc28466b85 --- /dev/null +++ b/translations/lrc_oc.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="oc" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Ieu</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Connexion</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Recèrca</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Invitacion recebuda</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Contacte ajustat</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Sonada sortissenta mancada</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Sonada dintrada mancada</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Invitacion acceptada</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>D’ACÃ’RDI</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Lançar una visioconferéncia</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Lançar sonada</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Enviar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Enviar un fichiè</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Daissar un messatge vidèo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Daissar un messatge à udio</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Acceptar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Refusar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Blocar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>Ara meteis</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Suprimir</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Tornar ensajar</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Recèrca…</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_pa.ts b/translations/lrc_pa.ts new file mode 100644 index 0000000000000000000000000000000000000000..103affd61a3b4ccf732a0c7c42ccb4aa347e99c0 --- /dev/null +++ b/translations/lrc_pa.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="pa" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>ਮੈਂ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>ਰੋਕ ਕੇ ਰੱਖੀ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>ਗੱਲ ਚੱਲ ਰਹੀ ਹੈ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>ਗੜਬੜ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>ਕਾਲ ਆ ਰਹੀ ਹੈ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>ਕਾਲ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>ਕਨੈਕਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>ਖੋਜਿਆ ਜਾ ਰਿਹਾ ਹੈ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>ਸੰਚਾਰ ਸ਼à©à¨°à©‚ ਹੋਇਆ</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>ਸੱਦਾ ਮਿਲਿਆ</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>ਸੰਪਰਕ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 ਸ਼ਾਮਲ ਹੋਇਆ</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 ਲਾਗਆਉਟ ਹੈ</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>ਜਾਂਦੀ ਕਾਲ</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>ਆਉਂਦੀ ਕਾਲ</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>ਖà©à©°à¨à©€ ਜਾਂਦੀ ਕਾਲ</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>ਖà©à©°à¨à©€ ਆਉਂਦੀ ਕਾਲ</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>Ø·Û’ شدÛ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>ਘੰਟੀ ਵੱਜ ਰਹੀ ਹੈ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>ਠੀਕ ਹੈ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>ਰà©à¨à©‡à¨µà©‡à¨‚ ਵਿੱਚ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>à¨à©‡à¨œà©‹</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>ਵਾਰਤਾਲਾਪ ਦੇ ਅੰਤ ਤੱਕ ਸਕà©à¨°à©Œà¨² ਕਰੋ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>ਫ਼ਾਈਲ à¨à©‡à¨œà©‹</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>ਮਨਜ਼ੂਰ ਕਰੋ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>ਨਾ-ਮਨਜ਼ੂਰ ਕਰੋ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>ਬੰਦਸ਼ ਲਗਾਓ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>ਰੱਦ ਕੀਤਾ ਗਿਆ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>ਮਿਟਾਓ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_pl.ts b/translations/lrc_pl.ts new file mode 100644 index 0000000000000000000000000000000000000000..a2d6ae3c811ece6eb78a0b61939233a2bbf19935 --- /dev/null +++ b/translations/lrc_pl.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="pl" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Ja</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Czekanie</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Rozmawianie</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>BÅÄ„D</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>PrzychodzÄ…ce</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Dzwonienie</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>ÅÄ…czenie</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Wyszukiwanie</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Nieaktywne</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>ZakoÅ„czono</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Przekroczony czas</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Peer zajÄ™ty</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>PoÅ‚Ä…czenie siÄ™ powiodÅ‚o </translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Otrzymano zaproszenie</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Kontakt dodany</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 doÅ‚Ä…czyÅ‚</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 opuÅ›ciÅ‚</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>PoÅ‚Ä…czenie wychodzÄ…ce</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>PoÅ‚Ä…czenie przychodzÄ…ce</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Nieodebrane poÅ‚Ä…czenie wychodzÄ…ce</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Nieodebrane poÅ‚Ä…czenie przychodzÄ…ce</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Zaakceptowano zaproszenie</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>domyÅ›lne</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Null</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Próbowanie</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Dzwonienie</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>Jest Przekazywane</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>W kolejce</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>Progres</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>OK</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Zaakceptowane</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Wiele Wyborów</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Przeniesione Na StaÅ‚e</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Przeniesione Tymczasowo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Używaj Proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Alternatywna UsÅ‚uga</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>NieprawidÅ‚owe zapytanie</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Nieautoryzowany</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Wymagana PÅ‚atność</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Zabroniony</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Nie Znaleziono</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Metoda nie dozwolona</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>Nieakceptowalne</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Wymagane Uwierzytelnienie Proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>ProÅ›ba przekroczyÅ‚a czas oczekiwania</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>ZniknÄ…Å‚</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>Żądanie URI za dÅ‚ugie</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>ZÅ‚e rozszeżenie</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Rozszerzenie jest wymagane</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Zbyt maÅ‚y zegar sesji</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>InterwaÅ‚ zbyt krótki</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Tymczasowo niedostÄ™pny</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Adres niekompletny</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>ZajÄ™ty</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Przekroczony czas odpowiedzi serwera</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Wersja nie jest wpierana</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Wiadomość zbyt dÅ‚uga</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>ZajÄ™ty wszÄ™dzie</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Schowaj chat</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Rozpocznij rozmowÄ™ wideo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Pokaż dostÄ™pne wtyczki</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Wykonaj poÅ‚Ä…czenie gÅ‚osowe</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Dodaj do rozmowy</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Odblokuj konto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>WyÅ›lij</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>Opcje</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>PrzewiÅ„ do koÅ„ca konwersacji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>WyÅ›lij plik</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Dodaj emoji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Zostaw wiadomość wideo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Zostaw wiadomość gÅ‚osowÄ…</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>Napisz do {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Akceptuj</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Odmów</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>Nie udaÅ‚o siÄ™ nawiÄ…zać kontaktu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>Czekanie na kontakt</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>PrzychodzÄ…cy transfer</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>Przekroczono czas czekajÄ…c na kontakt</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Blokuj</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Uwaga: interakcja utworzy nowy kontakt.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>nie jest w twoich kontaktach</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Uwaga: możesz automatycznie zaakceptować to zaproszenie poprzez wysÅ‚anie wiadmoÅ›ci.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>{0} dni temu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>{0} godzin temu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>{0} minut temu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Anulowano</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>W trakcie</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>%d dni temu </translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>%d godzin temu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>%d minut temu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>jeden dzieÅ„ temu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>jednÄ… godzinÄ™ temu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>teraz</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Nie powiodÅ‚o siÄ™</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>UsuÅ„</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Ponów</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Szukanie...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>NieprawidÅ‚owe ID</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Nazwa użytkownika nieznaleziona</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>ZÅ‚e URI</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_pl_PL.ts b/translations/lrc_pl_PL.ts new file mode 100644 index 0000000000000000000000000000000000000000..917114f5e1482d7f6da7275cf4989bca83a6df9a --- /dev/null +++ b/translations/lrc_pl_PL.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="pl_PL" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Ja</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Czekanie</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Rozmawianie</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>BÅÄ„D</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>PrzychodzÄ…ce</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Dzwonienie</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>ÅÄ…czenie</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Wyszukiwanie</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Nieaktywne</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>ZakoÅ„czono</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Przekroczony czas</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Peer zajÄ™ty</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>PoÅ‚Ä…czenie siÄ™ powiodÅ‚o </translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Otrzymano zaproszenie</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Kontakt dodany</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 doÅ‚Ä…czyÅ‚</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 opuÅ›ciÅ‚</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>PoÅ‚Ä…czenie wychodzÄ…ce</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>PoÅ‚Ä…czenie przychodzÄ…ce</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Nieodebrane poÅ‚Ä…czenie wychodzÄ…ce</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Nieodebrane poÅ‚Ä…czenie przychodzÄ…ce</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Zaakceptowano zaproszenie</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>domyÅ›lne</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Null</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Próbowanie</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Dzwonienie</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>Jest Przekazywane</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>W kolejce</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>PostÄ™p</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>OK</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Zaakceptowane</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Wiele Wyborów</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Przeniesione Na StaÅ‚e</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Przeniesione Tymczasowo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Używaj Proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Alternatywna UsÅ‚uga</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>NieprawidÅ‚owe zapytanie</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Nieautoryzowany</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Wymagana PÅ‚atność</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Zabroniony</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Nie Znaleziono</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Metoda nie dozwolona</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>Nieakceptowalne</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Wymagane Uwierzytelnienie Proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>ProÅ›ba przekroczyÅ‚a czas oczekiwania</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>ZniknÄ…Å‚</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>Żądanie URI za dÅ‚ugie</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>ZÅ‚e rozszeżenie</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Rozszerzenie jest wymagane</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Zbyt maÅ‚y zegar sesji</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>InterwaÅ‚ zbyt krótki</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Tymczasowo niedostÄ™pny</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Adres niekompletny</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>ZajÄ™ty</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Przekroczony czas odpowiedzi serwera</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Wersja nie jest wpierana</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Wiadomość zbyt dÅ‚uga</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>ZajÄ™ty wszÄ™dzie</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Schowaj chat</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Rozpocznij rozmowÄ™ wideo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Pokaż dostÄ™pne wtyczki</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Wykonaj poÅ‚Ä…czenie gÅ‚osowe</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Dodaj do rozmowy</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Odblokuj konto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>WyÅ›lij</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>Opcje</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>PrzewiÅ„ do koÅ„ca konwersacji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>WyÅ›lij plik</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Dodaj emoji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Nagraj wiadomość wideo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Nagraj wiadomość gÅ‚osowÄ…</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>Napisz do {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Akceptuj</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Odmów</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>Nie udaÅ‚o siÄ™ nawiÄ…zać kontaktu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>Czekanie na kontakt</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>PrzychodzÄ…cy transfer</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>Przekroczono czas czekajÄ…c na kontakt</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Blokuj</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Uwaga: interakcja utworzy nowy kontakt.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>nie jest w twoich kontaktach</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Uwaga: możesz automatycznie zaakceptować to zaproszenie poprzez wysÅ‚anie wiadmoÅ›ci.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>{0} dni temu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>{0} godzin temu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>{0} minut temu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Anulowano</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>W trakcie</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>%d dni temu </translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>%d godzin temu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>%d minut temu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>jeden dzieÅ„ temu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>jednÄ… godzinÄ™ temu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>teraz</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Nie powiodÅ‚o siÄ™</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>UsuÅ„</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Ponów</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Szukanie</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>NieprawidÅ‚owe ID</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Nazwa użytkownika nieznaleziona</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>ZÅ‚e URI</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_pt.ts b/translations/lrc_pt.ts new file mode 100644 index 0000000000000000000000000000000000000000..6f54ef7412a96b6daf2647c4dfebab4666078d8f --- /dev/null +++ b/translations/lrc_pt.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="pt" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Eu</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Modo de espera</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>A falar</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>ERRO</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>A receber</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>A chamar</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>A conectar</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>A pesquisar</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Inativo</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Terminado</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Tempo limite excedido</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Contacto ocupado</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Comunicação estabelecida</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Convite recebido</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Contacto adicionado</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 entrou</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 saiu</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Chamada efetuada</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Chamada recebida</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Chamadas efetuadas perdidas</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Chamadas recebidas perdidas</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Convite aceite</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>predefinição</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Nulo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>A tentar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>A tocar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>A ser reencaminhado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>Na fila</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>A decorrer</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>OK</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Aceite</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Várias escolhas</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Movido permanentemente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Movido temporariamente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Usar proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Serviço alternativo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Pedido inválido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Não autorizado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Necessário pagamento</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Proibido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Não encontrado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Método não permitido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>Não aceitável</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Necessário autenticação de proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>O pedido excedeu o tempo limite</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Foi-se</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Entidade do pedido demasiado grande</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>URI de pedido demasiado longo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Tipo de media não suportado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Esquema URI não suportado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Extensão inválida</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Necessária extensão</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Temporizador de sessão demasiado pequeno</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Intervalo demasiado breve</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Não disponÃvel temporariamente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation> A chamada TSX não existe</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Detetado loop</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Demasiados saltos</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Endereço incompleto</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>AmbÃguo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Ocupado(a)</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Pedido terminado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Evento inválido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Pedido atualizado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Pedido pendente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Não decifrável</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Erro interno do servidor</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Não implementado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Gateway inválido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Serviço indisponÃvel</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Tempo de resposta do servidor excedido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Versão não suportada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Mensagem demasiado grande</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Falha nos pré-requisitos</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Ocupado em todo o lado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Chamada recusada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>Não existe em lugar nenhum</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>Não aceite em lugar nenhum</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Ocultar visualização da conversa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Fazer video-chamada</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Mostrar extensões disponÃveis</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Fazer chamada de áudio</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Adicionar à s conversas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Desbanir contacto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Enviar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>Opções</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Ir para o fim da conversa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Enviar ficheiro</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Adicionar emoji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Deixe uma mensagem de vÃdeo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Deixe uma mensagem de áudio</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Copiar para downloads</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>Escrever para {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>Enviou a você uma solicitação de conversa.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Olá, gostaria de participar da conversa?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Você aceitou o pedido de conversa.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>Estamos aguardando por outro dispositivo para sincronizar a conversa.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Aceitar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Recusar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>Não é possÃvel fazer contato</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>Aguardando pelo contato</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>Recebendo transferência</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>O tempo de aguardo pelo contato chegou ao fim</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Bloquear</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Nota: uma interação irá criar um contacto novo.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>is not in your contacts</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Nota: pode aceitar este convite automaticamente enviando uma mensagem.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>{0} days ago</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>{0} hours ago</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>{0} minutes ago</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Cancelada</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>Em andamento</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>há %d dias</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>há %d horas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>há %d minutos</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>há um dia</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>há uma hora</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>agora mesmo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Falha</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Eliminar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Tentar novamente</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>A pesquisar…</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>ID inválido</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Nome de usuário não encontrado</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>Não consegui procurar...</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Mau esquema de URI</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_pt_BR.ts b/translations/lrc_pt_BR.ts new file mode 100644 index 0000000000000000000000000000000000000000..97bec433186c33a371fd46d6d22fc50fa3591637 --- /dev/null +++ b/translations/lrc_pt_BR.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="pt_BR" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Eu</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Aguarde</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Falando</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>ERRO</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Entrada</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Chamando</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Conectando</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Pesquisando</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Inativo</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Terminado</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Tempo esgotado</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Pessoa ocupada</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Comunicação estabelecida</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Convite recebido</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Contato adicionado</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 ingressou</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 saiu</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Chamada efetuada</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Chamada recebida</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Chamadas efetuadas perdidas</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Chamadas recebidas perdidas</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Convite aceito</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>predefinição</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Nulo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Tentando</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Tocando</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>Está sendo encaminhado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>Esperando</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>Progresso</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>OK</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Aceito</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Múltiplas Escolhas</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Movido Permanentemente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Movido Temporariamente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Usar proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Serviço Alternativo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Pedido Inadequado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Não autorizado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Pagamento Requerido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Proibido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Não Encontrado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Método Não Permitido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>Não Aceitável</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Autenticação de Proxy Necessária</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>A requisição excedeu o tempo limite</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Perdido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Pedido Muito Grande</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>Pedido de URI Muito Longo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>MÃdia Não Suportada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Tipo de URI Sem Suporte</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Complemento Inadequado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Complemento Necessário</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Temporizador de Sessão Muito Pequeno</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Intervalo Muito Curto</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Temporariamente IndisponÃvel</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>Chamada TSX Não Existe</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Loop Detectado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Muitos Ressaltos</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Endereço Incompleto</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>AmbÃguo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Ocupado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Pedido Terminado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Evento Inadequado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Pedido Atualizado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Pedido Pendente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Indecifrável</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Erro Interno do Servidor</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Não Implementado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Gateway Inadequado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Serviço IndisponÃvel</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Tempo do Servidor Esgotou</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Versão Não Suportada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Mensagem Muito Grande</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Requisito Insuficiente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Ocupado em Toda Parte</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Chamada Recusada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>Não Existe em Nenhum Lugar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>Não Aceitável em Qualquer Lugar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Ocultar visão do bate-papo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Fazer videochamada</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Mostrar extensões disponÃveis</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Fazer chamada de áudio</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Adicionar à s conversas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Contato não banido</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Enviar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>Opções</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Rolar para o fim da conversa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Enviar arquivo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Adicionar emoji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Deixe uma mensagem de vÃdeo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Deixe uma mensagem de áudio</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Copiar para downloads</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>Escrever para {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>Enviou a você uma solicitação de conversa.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Olá, gostaria de participar da conversa?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Você aceitou o pedido de conversa.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>Estamos aguardando por outro dispositivo para sincronizar a conversa.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Aceitar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Recusar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>Não é possÃvel fazer contato</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>Aguardando pelo contato</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>Recebendo transferência</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>O tempo de aguardo pelo contato chegou ao fim</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Bloquear</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Observação: uma interação criará um novo contato</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>não está em seus contatos</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Observação: você pode aceitar automaticamente este convite enviando uma mensagem.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>{0} dias atrás</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>{0} horas atrás</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>{0} minutos atrás</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Cancelada</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>Em andamento</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>%d dias atrás</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>%d horas atrás</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>%d minutos atrás</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>um dia atrás</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>uma hora atrás</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>Agora</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Falha</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Deletar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Tente novamente</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Buscando...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>ID inválido</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Nome de usuário não encontrado</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>Não consegui procurar...</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Mau esquema de URI</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_pt_PT.ts b/translations/lrc_pt_PT.ts new file mode 100644 index 0000000000000000000000000000000000000000..1b12258642ab637ee987d6c737ae25d05d2dd813 --- /dev/null +++ b/translations/lrc_pt_PT.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="pt_PT" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Eu</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Modo de espera</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>A falar</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>ERRO</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>A receber</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>A chamar</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>A conectar</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>A pesquisar</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Inativo</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Terminado</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Tempo limite excedido</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Contacto ocupado</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Comunicação estabelecida</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Convite recebido</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Contacto adicionado</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 entrou</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>% 1 saiu</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Chamada efetuada</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Chamada recebida</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Chamadas efetuadas perdidas</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Chamadas recebidas perdidas</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Convite aceite</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>predefinição</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Nulo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>A tentar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>A tocar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>A ser reencaminhado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>Na fila</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>A decorrer</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>OK</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Aceite</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Várias escolhas</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Movido permanentemente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Movido temporariamente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Usar proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Serviço alternativo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Pedido inválido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Não autorizado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Necessário pagamento</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Proibido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Não encontrado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Método não permitido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>Não aceitável</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Necessário autenticação de proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>O pedido excedeu o tempo limite</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Foi-se</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Entidade do pedido demasiado grande</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>URI de pedido demasiado longo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Tipo de media não suportado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Esquema URI não suportado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Extensão inválida</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Necessária extensão</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Temporizador de sessão demasiado pequeno</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Intervalo demasiado breve</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Não disponÃvel temporariamente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation> A chamada TSX não existe</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Detetado loop</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Demasiados saltos</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Endereço incompleto</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>AmbÃguo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Ocupado(a)</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Pedido terminado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Evento inválido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Pedido atualizado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Pedido pendente</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Não decifrável</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Erro interno do servidor</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Não implementado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Gateway inválido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Serviço indisponÃvel</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Tempo de resposta do servidor excedido</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Versão não suportada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Mensagem demasiado grande</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Falha nos pré-requisitos</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Ocupado em todo o lado</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Chamada recusada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>Não existe em lugar nenhum</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>Não aceite em lugar nenhum</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Ocultar visualização da conversa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Fazer video-chamada</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Mostrar extensões disponÃveis</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Fazer chamada de áudio</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Adicionar à s conversas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Desbanir contacto</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Enviar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>Opções</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Ir para o fim da conversa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Enviar ficheiro</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Adicionar emoji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Deixe uma mensagem de vÃdeo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Deixe uma mensagem de áudio</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Copiar para downloads</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>Escrever para {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>Enviou a você uma solicitação de conversa.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Olá, gostaria de participar da conversa?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Você aceitou o pedido de conversa.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>Estamos aguardando por outro dispositivo para sincronizar a conversa.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Aceitar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Recusar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>Não é possÃvel fazer contato</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>Aguardando pelo contato</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>Recebendo transferência</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>O tempo de aguardo pelo contato chegou ao fim</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Bloquear</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Nota: uma interação irá criar um contacto novo.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>is not in your contacts</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Nota: pode aceitar este convite automaticamente enviando uma mensagem.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>{0} days ago</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>{0} hours ago</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>{0} minutes ago</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Cancelada</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>Em andamento</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>há %d dias</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>há %d horas</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>há %d minutos</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>há um dia</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>há uma hora</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>agora mesmo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Falha</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Eliminar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Tentar novamente</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>A pesquisar…</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>ID inválido</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Nome de usuário não encontrado</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>Não foi possÃvel encontrar...</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Mau esquema de URI</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_ro.ts b/translations/lrc_ro.ts new file mode 100644 index 0000000000000000000000000000000000000000..832c702b1534fe06e579f6a20ea9ef09f11a89f9 --- /dev/null +++ b/translations/lrc_ro.ts @@ -0,0 +1,426 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS language="ro" sourcelanguage="en" version="2.0"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="315"/> + <source>Me</source> + <translation>Eu</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="60"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="62"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="64"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="66"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="68"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="70"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="72"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="74"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="76"/> + <location filename="../src/libclient/api/call.h" line="82"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="78"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="80"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="84"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="136"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="871"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="133"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="869"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="107"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="113"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="867"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="109"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="120"/> + <source>Incoming call</source> + <translation>Apel</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="116"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="865"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="123"/> + <source>Missed incoming call</source> + <translation>Apel pierdut</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="138"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="873"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="322"/> + <location filename="../src/libclient/avmodel.cpp" line="343"/> + <source>default</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="48"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="49"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="50"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="51"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="52"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="53"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="54"/> + <source>OK</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="55"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="56"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="57"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="58"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="59"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="405"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="765"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="768"/> + <source>Registered name not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="771"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="371"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_ro_RO.ts b/translations/lrc_ro_RO.ts new file mode 100644 index 0000000000000000000000000000000000000000..9bf8216faa2d5785555e3710e7a37a5ce7843087 --- /dev/null +++ b/translations/lrc_ro_RO.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="ro_RO" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Eu</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Pauză</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Convorbire</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>EROARE</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>SoseÈ™te</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Sună</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Se conectează</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Căutare</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Inactiv</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Terminat</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Timp expirat</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Ocupat</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Legătură stabilită</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>InvitaÈ›ie primită</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Contact adăugat</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation>%1 a fost invitat să participe</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 s-a alăturat</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 a ieÈ™it</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation>%1 a fost dat afară</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation>%1 a fost reprimit</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation>Grup creat</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Apel efectuat</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Apel primit</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Apel efectuat nepreluat</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Apel pierdut</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>InvitaÈ›ie acceptată</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>prestabilit</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Nul</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Probă</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Sună</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>Se trimite</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>ÃŽn aÈ™teptare</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>ÃŽn curs</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Bine</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Acceptat</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Alegeri multiple</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Mutat permanent</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Mutat temporar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>FoloseÈ™te Proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Serviciu alternativ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Cerere greÈ™ită</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Neautorizat</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Plată obligatorie</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Interzis</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Nu a fost găsit</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Metodă nepermisă</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>Inacceptabil</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Autentificare pentru Proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Timpul a expirat</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Absent</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Elementul cerut este prea mare</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>URI-ul cerut este prea lung</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Tip de media neacceptat</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Schemă URI neacceptată</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Extensie greÈ™ită</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Extensie necesară</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Timpul sesiunii este prea scurt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Interval prea scurt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Temporar indisponibil</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>Apelul TSX nu există</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Loop descoperit</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Prea multe Hop-uri</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Adresă incompletă</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>Neclar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Ocupat</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Cerere terminată</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Eveniment greÈ™it</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Cerere actualizată</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Cerere în curs</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Indescifrabil</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Eroare internă a serverului</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Neimplementat</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Poartă greÈ™ită</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Serviciu indisponibil</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Timpul a expirat</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Versiune incompatibilă</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Mesaj prea mare</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>EÈ™ec al precondiÈ›iei</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Ocupat peste tot</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Apel refuzat</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>Nu există nicăieri</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>Nu este acceptat nicăieri</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Ascunde discuÈ›ia</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Fă apel video</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Arată extensiile disponibile</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Fă apel vocal</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Adaugă la conversaÈ›ii</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Deblochează contactul</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Trimite</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>OpÈ›iuni</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Saltă la ultimul</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Trimite un fiÈ™ier</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Adaugă emoji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Trimite mesaj video</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Trimite mesaj vocal</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Copiază pentru a descărca</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>Scrie pentru {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>È›i-a trimis o invitaÈ›ie la conversaÈ›ie.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Vrei să participi la conversaÈ›ie?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Ai acceptat invitaÈ›ia la conversaÈ›ie.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>Se aÈ™teaptă ca È™i alte aparate să sincronizeze conversaÈ›ia.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Acceptă</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Refuză</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>Imposibil de contactat</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>ÃŽn aÈ™teptare</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>Transfer primit</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>Timpul de aÈ™teptare a expirat</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Blochează</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Aviz: o acÈ›iune va crea un nou contact.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>nu e în contactele tale</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Aviz: poÈ›i accepta automat această invitaÈ›ie trimițînd un mesaj.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>acum {0} zile</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>acum {0} ore</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>acum {0} minute</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Anulat</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>ÃŽn curs</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>acum %d zile</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>acum %d ore</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>acum %d minute</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>acum o zi</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>acum o oră</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>chiar acum</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>EÈ™ec</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Șterge</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>ÃŽncearcă din nou</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Căutare...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>ID greÈ™it</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Numele de utilizator nu a fost găsit</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>Căutare imposibilă...</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Schemă URI greÈ™ită</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_ru.ts b/translations/lrc_ru.ts new file mode 100644 index 0000000000000000000000000000000000000000..4cffdb770b9a55fd300c5c4b09f77e47ac748eec --- /dev/null +++ b/translations/lrc_ru.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="ru" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Я</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Удержать</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Разговор</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>ОШИБКÐ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>ВходÑщий</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Вызов</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Подключение</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>ПоиÑк</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Ðеактивен</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Завершён</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Ð’Ñ€ÐµÐ¼Ñ Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>УчаÑтник занÑÑ‚</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Соединение уÑтановлено</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Получено приглашение</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Контакт добавлен</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation>%1 был приглашен приÑоединитьÑÑ</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 приÑоединÑетÑÑ</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 вышел</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation>% 1 был выгнан</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation>%1 был повторно добавлен</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>ИÑходÑщий вызов</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>ВходÑщий вызов</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>ÐепринÑтый иÑходÑщий вызов</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Пропущенный входÑщий вызов</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Приглашение принÑто</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>По умолчанию</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>ПуÑтой</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Попытка</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Звонок</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>Было отправлено</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>ПоÑтавлено в очередь</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>ПрогреÑÑ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Ð’ порÑдке</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>ПринÑто</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>МножеÑтво вариантов</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Переехал навÑегда</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Временно перехал</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>ИÑпользовать прокÑи</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>ÐÐ»ÑŒÑ‚ÐµÑ€Ð½Ð°Ñ‚Ð¸Ð²Ð½Ð°Ñ Ñлужба</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Ðеверный запроÑ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Ðеавторизовано</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>ТребуетÑÑ Ð¾Ð¿Ð»Ð°Ñ‚Ð°</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Запрещено</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Ðе найдено</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Метод не разрешен</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>ÐедопуÑтимо</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>ТребуетÑÑ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ° подлинноÑти прокÑи</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Ð’Ñ€ÐµÐ¼Ñ Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñа</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Прошло</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Запрошенный объект Ñлишком большой</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>Запрошенный URL Ñлишком длинный</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Ðеподдерживаемый тип медиа</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Ðеподдерживаемый Ñхема URI</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Ðеверное раÑширение</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>ТребуетÑÑ Ñ€Ð°Ñширение</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Таймер ÑеÑÑии Ñлишком мал</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Интервал Ñлишком короткий</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Временно недоÑтупен</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>Вызываемый TSX не ÑущеÑтвует</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Обнаружена петлÑ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Слишком много переходов</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Ðеполный адреÑ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>ДвуÑмыÑленный</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>ЗанÑто</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð¿Ñ€ÐµÐºÑ€Ð°Ñ‰ÐµÐ½</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Ðекорректное Ñобытие</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð¾Ð¶Ð¸Ð´Ð°ÐµÑ‚ выполнениÑ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Ðеразборчивый</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>ВнутреннÑÑ Ð¾ÑˆÐ¸Ð±ÐºÐ° Ñервера</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Ðе реализовано</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Ðекорректный шлюз</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Ð¡ÐµÑ€Ð²Ð¸Ñ Ð½ÐµÐ´Ð¾Ñтупен</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Тайм-аут Ñервера</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>ВерÑÐ¸Ñ Ð½Ðµ поддерживаетÑÑ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Слишком большое Ñообщение</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Сбой предуÑловиÑ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>ЗанÑÑ‚ везде</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Вызов отклонен</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>Ðе ÑущеÑтвует нигде</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>Ðе приемлемо нигде</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Скрыть чат</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Сделать видеозвонок</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Показать доÑтупные плагины</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Сделать аудиозвонок</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Добавить к контактам</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Разблокировать контакт</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Отправить</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>Параметры</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Прокрутить до конца беÑеды</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Отправить файл</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Добавить Ñмоджи</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>ОÑтавить видео Ñообщение</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>ОÑтавить аудио Ñообщение</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Копировать в загрузки</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>ЗапиÑÑŒ в {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>отправил вам Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° беÑеду.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Привет, вы хотите приÑоеденитьÑÑ Ðº разговору?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Ð’Ñ‹ принÑли Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° беÑеду.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>Мы ожидаем пока другое уÑтройÑтво Ñинхронизирует перепиÑку.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>ПринÑÑ‚ÑŒ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Отказать</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>Ðе удалоÑÑŒ уÑтановить контакт</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>Ожидание контакта</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>ВходÑщий перевод</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>Тайм-аут Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð°</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Заблокировать</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Примечание: при взаимодейÑтвии будет Ñоздан новый контакт.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>отÑутÑтвует в ваших контактах</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Примечание: Ð’Ñ‹ можете автоматичеÑки принÑÑ‚ÑŒ Ñто приглашение, отправив Ñообщение.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>{0} дней назад</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>{0} чаÑов назад</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>{0} минут назад</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Отменено</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>Текущий</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>%d дней назад</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>%d чаÑов назад</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>%d минут назад</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>один день назад</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>один Ñ‡Ð°Ñ Ð½Ð°Ð·Ð°Ð´</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>прÑмо ÑейчаÑ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Ошибка</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Удалить</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Повторить</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>ПоиÑк…</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>Ðеверный ID</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð½Ðµ найдено</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>Ðе могу найти ...</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>ÐÐµÐºÐ¾Ñ€Ñ€ÐµÐºÑ‚Ð½Ð°Ñ Ñхема URI</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_ru_RU.ts b/translations/lrc_ru_RU.ts new file mode 100644 index 0000000000000000000000000000000000000000..15cc5106cfb5b21f692686cc58692bea3d29e8b6 --- /dev/null +++ b/translations/lrc_ru_RU.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="ru_RU" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Мне</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Удержание</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Говорить</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>ОШИБКÐ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>ВходÑщий</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>звонÑщий</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Подключение</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>ПоиÑк</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Ðеактивный</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Завершено</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Ð’Ñ€ÐµÐ¼Ñ Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Ðбонент занÑÑ‚</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Соединение уÑтановлено</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Получено приглашение</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Контакт добавлен</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation>%1 был приглашен приÑоединитьÑÑ</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 приÑоединÑетÑÑ</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 вышел</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation>% 1 был выгнан</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation>%1 был повторно добавлен</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>ИÑходÑщий вызов</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>ВходÑщий вызов</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Пропущенный иÑходÑщий</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Пропущенный входÑщий</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Приглашение принÑто</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>по-умолчанию</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>ПуÑтой</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>ПытаемÑÑ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Вызов</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>Будет перенаправлено</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>Ð’ очереди</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>Вызов</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Ð’ порÑдке</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>ПринÑто</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>МножеÑтвенный выбор</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Перемещено навÑегда</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Временно перемещено</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>ИÑпользовать прокÑи</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Ðльтернативный ÑервиÑ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Ðеверный запроÑ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Ðеавторизовано</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>ТребуетÑÑ Ð¾Ð¿Ð»Ð°Ñ‚Ð°</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Запрещено</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Ðе найдено</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Метод не поддерживаетÑÑ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>Ðе принÑто</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>ТребуетÑÑ Ð°ÑƒÑ‚ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ†Ð¸Ñ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Ð’Ñ€ÐµÐ¼Ñ Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñа</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Прошло</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Ð—Ð°Ð¿Ñ€Ð¾Ñ Ñлишком большой</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>Запрошенный URI Ñлишком большой</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Ðеподдерживаемый тип медиа</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>ÐÐµÐ¿Ð¾Ð´Ð´ÐµÑ€Ð¶Ð¸Ð²Ð°ÐµÐ¼Ð°Ñ Ñхема данных</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Ðеверное раÑширение</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>ТребуетÑÑ Ñ€Ð°Ñширение</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Таймер ÑеÑÑии Ñлишком мал</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Интервал Ñлишком короткий</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Временно недоÑтупно</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>Вызываемый TSX не ÑущеÑтвует</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Ð’ÑÑ‘ зациклилоÑÑŒ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Слишком много прыжков</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Ðеполный адреÑ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>ДвуÑмыÑленный</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>ЗанÑÑ‚</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð¿Ñ€ÐµÑ€Ð²Ð°Ð½</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Ðекорректное Ñобытие</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð¾Ð±Ð½Ð¾Ð²Ð»Ñ‘Ð½</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð¾Ð¶Ð¸Ð´Ð°ÐµÑ‚ выполнениÑ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Ðеразборчивый</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>ВнутреннÑÑ Ð¾ÑˆÐ¸Ð±ÐºÐ° Ñервера</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Ðе реализовано</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Ðекорректный шлюз</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Ð¡ÐµÑ€Ð²Ð¸Ñ Ð½ÐµÐ´Ð¾Ñтупен</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Сервер не отвечает</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>ВерÑÐ¸Ñ Ð½Ðµ поддерживаетÑÑ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Сообщение Ñлишком большое</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Сбой предуÑловиÑ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>ЗанÑÑ‚ везде</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Звонок Ñброшен</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>Ðе ÑущеÑтвует нигде</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>Ðе приемлемо нигде</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Скрыть чат</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Сделать видеозвонок</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Показать доÑтупные плагины</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Сделать аудиозвонок</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Добавить к контактам</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Разблокировать контакт</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Отправть</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>ÐаÑтройки</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Прокрутить до конца беÑеды</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Отправить файл</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Добавить Ñмоджи</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>ОÑтавить видеоÑообщение</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>ОÑтавить аудио Ñообщение</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Копировать в загрузки</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>ЗапиÑÑŒ в {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>отправил вам Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° беÑеду.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Привет, вы хотите приÑоеденитьÑÑ Ðº разговору?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Ð’Ñ‹ принÑли Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° беÑеду.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>Мы ожидаем пока другое уÑтройÑтво Ñинхронизирует перепиÑку.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>ПринÑÑ‚ÑŒ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Отказать</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>Ðе удалоÑÑŒ уÑтановить контакт</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>Ожидание контакта</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>ВходÑщий перевод</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>Тайм-аут Ð¾Ð¶Ð¸Ð´Ð°Ð½Ð¸Ñ ÐºÐ¾Ð½Ñ‚Ð°ÐºÑ‚Ð°</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Заблокировать</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Справка: будет Ñоздан новый контакт.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>нет в ваших контактах</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Справка: вы можете автоматичеÑки принÑÑ‚ÑŒ Ñто приглашение отправив Ñообщение.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>{0} дней назад</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>{0} чаÑов назад</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>{0} минут назад</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Отменено</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>Текущий</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>%d дней назад</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>%d чаÑов назад</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>%d минут назад</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>вчера</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>Ñ‡Ð°Ñ Ð½Ð°Ð·Ð°Ð´</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>только что</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Ошибка</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Удалить</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Повтор</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>ПоиÑк...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>Ðеверный ID</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ Ð½Ðµ найдено</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>Ðевозможно найти...</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>ÐÐµÐ²ÐµÑ€Ð½Ð°Ñ Ñхема URI</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_si.ts b/translations/lrc_si.ts new file mode 100644 index 0000000000000000000000000000000000000000..79e01bec18c0a1e07cbc4900ba1f4a455290de75 --- /dev/null +++ b/translations/lrc_si.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="si" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 එකà¶à·” වී ඇà¶</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 ලොග් අවුට් වී ඇà¶</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>පෙරනිමිය</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>හරි</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>ගොනුව යවන්න</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>අවලංගු කළà·</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_sk.ts b/translations/lrc_sk.ts new file mode 100644 index 0000000000000000000000000000000000000000..6de1390fc7191a6de1781aa13ccd85eaf714e313 --- /dev/null +++ b/translations/lrc_sk.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="sk" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Ja</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>PodržaÅ¥</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Volanie</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>CHYBA</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Prichádzajúci</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Volanie</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Pripájanie</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Hľadanie</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>NeaktÃvny</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>UkonÄený</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>ÄŒasový limit vyprÅ¡al</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Peer zaneprázdnený</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Spojenie nadviazané</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Bola prijatá pozvánka</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Kontakt pridaný</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>PoužÃvateľ %1 sa pripojil</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>PoužÃvateľ %1 odiÅ¡iel</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Odchádzajúci hovor</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Prichádzajúci hovor</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>ZmeÅ¡kaný odchádzajúci hovory</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>ZmeÅ¡kaný prÃchodzà hovor</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Pozvánka prijatá</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>predvolený</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Null</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Pokúšam sa</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Zvonenie</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>Presmeruje sa</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>Zaradené</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>Priebeh</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>V poriadku</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Prijaté</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Viaceré možnosti</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Moved Permanently</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Moved Temporarily</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>PoužiÅ¥ Proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>AlternatÃvna služba</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Bad Request</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Unauthorized</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Payment Required</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Forbidden</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Not Found</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Method Not Allowed</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>Not Acceptable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Proxy Authentication Required</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>ÄŒas na splnenie žiadosti vyprÅ¡al</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Gone</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Request Entity Too Large</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>Request URI Too Long</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Unsupported Media Type</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Unsupported URI Scheme</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Bad Extension</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Extension Required</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Session Timer Too Small</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Interval Too Brief</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Temporarily Unavailable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>Call TSX Does Not Exist</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Loop Detected</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Too Many Hops</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Address Incomplete</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>Ambiguous</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Obsadené</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Request Terminated</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Bad Event</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Request Updated</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Request Pending</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Undecipherable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Internal Server Error</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Not Implemented</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Bad Gateway</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Service Unavailable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Server Timeout</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Version Not Supported</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Správa prÃliÅ¡ veľká</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Precondition Failure</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Busy Everywhere</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Hovor odmietnutý</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>Neexistuje</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>Neprijateľný</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>SkryÅ¥ chat</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>UskutoÄniÅ¥ video hovor</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>UskutoÄniÅ¥ audio hovor</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>PridaÅ¥ ku kontaktom</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>OdblokovaÅ¥ kontakt</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>PoslaÅ¥</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>PrejsÅ¥ na koniec konverzácie</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>PoslaÅ¥ súbor</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>PrijaÅ¥</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>OdmietnuÅ¥</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>BlokovaÅ¥</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Poznámka: vytvorà sa nový kontakt</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Poznámka: poslanÃm správy môžete automaticky prijaÅ¥ toto pozvanie</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>ZruÅ¡ené</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>Pred %d dňami</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>Pred %d hodinami</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>Pred %d minútami</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>VÄera</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>Pred hodinou</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>Práve teraz</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Chyba</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>VymazaÅ¥</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>SkúsiÅ¥ znovu</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Vyhľadávanie...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>Neplatné ID</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>Nenájdené</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Zlá URI schéma</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_sk_SK.ts b/translations/lrc_sk_SK.ts new file mode 100644 index 0000000000000000000000000000000000000000..77ef7689b7f97916ae00d35401b0656125199fee --- /dev/null +++ b/translations/lrc_sk_SK.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="sk_SK" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Ja</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>PodržaÅ¥</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Volanie</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>CHYBA</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Prichádzajúci</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Volanie</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Pripájanie</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Hľadanie</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>NeaktÃvny</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>UkonÄený</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>ÄŒasový limit vyprÅ¡al</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Peer zaneprázdnený</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Spojenie nadviazané</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Bola prijatá pozvánka</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Kontakt pridaný</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>PoužÃvateľ %1 sa pripojil</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>PoužÃvateľ %1 odiÅ¡iel</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Odchádzajúci hovor</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Prichádzajúci hovor</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>ZmeÅ¡kaný odchádzajúci hovory</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>ZmeÅ¡kaný prÃchodzà hovor</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Pozvánka prijatá</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>predvolený</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Null</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Pokúšam sa</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Zvonenie</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>Presmeruje sa</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>Zaradené</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>Priebeh</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>V poriadku</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Prijaté</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Viaceré možnosti</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Moved Permanently</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Moved Temporarily</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>PoužiÅ¥ Proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>AlternatÃvna služba</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Bad Request</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Unauthorized</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Payment Required</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Forbidden</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Not Found</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Method Not Allowed</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>Not Acceptable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Proxy Authentication Required</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>ÄŒas na splnenie žiadosti vyprÅ¡al</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Gone</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Request Entity Too Large</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>Request URI Too Long</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Unsupported Media Type</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Unsupported URI Scheme</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Bad Extension</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Extension Required</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Session Timer Too Small</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Interval Too Brief</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Temporarily Unavailable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>Call TSX Does Not Exist</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Loop Detected</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Too Many Hops</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Address Incomplete</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>Ambiguous</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Obsadené</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Request Terminated</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Bad Event</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Request Updated</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Request Pending</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Undecipherable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Internal Server Error</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Not Implemented</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Bad Gateway</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Service Unavailable</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Server Timeout</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Version Not Supported</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Správa prÃliÅ¡ veľká</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Precondition Failure</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Busy Everywhere</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Hovor odmietnutý</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>Neexistuje</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>Neprijateľný</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>SkryÅ¥ chat</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>UskutoÄniÅ¥ video hovor</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>UskutoÄniÅ¥ audio hovor</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>PridaÅ¥ ku kontaktom</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>OdblokovaÅ¥ kontakt</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>PoslaÅ¥</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>PrejsÅ¥ na koniec konverzácie</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>PoslaÅ¥ súbor</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>PrijaÅ¥</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>OdmietnuÅ¥</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>BlokovaÅ¥</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Poznámka: vytvorà sa nový kontakt</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Poznámka: poslanÃm správy môžete automaticky prijaÅ¥ toto pozvanie</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>ZruÅ¡ené</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>Pred %d dňami</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>Pred %d hodinami</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>Pred %d minútami</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>VÄera</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>Pred hodinou</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>Práve teraz</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Chyba</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>VymazaÅ¥</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>SkúsiÅ¥ znovu</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Vyhľadávanie...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>Neplatné ID</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>Nenájdené</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Zlá URI schéma</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_sl.ts b/translations/lrc_sl.ts new file mode 100644 index 0000000000000000000000000000000000000000..534bdbd1f33b840c1a7fb062d87e05e9a5cf59c1 --- /dev/null +++ b/translations/lrc_sl.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="sl" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Jaz</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Zadrži</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Pogovor</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>NAPAKA</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Dohodni</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Klicanje</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Povezovanje</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>iskanje</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Neaktiven</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>KonÄano</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>ÄŒasona omejitev</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Soležnik je zaseden</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Komunikacija vzpostavljena</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Povabilo je sprejeto</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Stik je dodan</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation>%1 vabljen/a, da se pridruži</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>Oseba %1 se je pridružila</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>Oseba %1 je odÅ¡la</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation>%1 izvržen/a</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation>%1 ponovno dodan/a</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation>Roj ustvarjen</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Odhodni klic</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Dohodni klic</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>ZgreÅ¡en odhodni klic</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>ZgreÅ¡en dohodni klic</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Povabilo je potrjeno</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>privzeto</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Null</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Poskus v teku</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Zvoni</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>Preusmerjanje naprej</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>V Äakalni vrsti</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>Napredek</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>V redu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Sprejeto</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>VeÄ izbir</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Trajno preseljen</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>ZaÄasno preseljen</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Uporabi posredniÅ¡ki strežnik</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Alternativna storitev</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>NapaÄen zahtevek</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Ni avtorizacije</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Zahtevano je plaÄilo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Prepovedano</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Ni najdeno</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Metoda ni dovoljena</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>Ni sprejemljivo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Zahtevana je overitev posredniÅ¡kega strežnika</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Zahteva je potekla</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>OdÅ¡lo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Zahtevana entiteta je prevelika</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>Zahtevek URI je predolg</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Nepodprta vrsta medija</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Shema URI ni podprta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>NapaÄna razÅ¡iritev</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Zahtevana je razÅ¡iritev</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>ÄŒasovnik seje je premajhen</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Interval je prekratek</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Trenutno ni na voljo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>Klicni TSX ne obstaja</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Zaznana zanka</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>PreveÄ preskokov</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Nepopoln naslov</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>Dovumno</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Zasedeno</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Zahteva je prekinjena</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>NapaÄen dogodek</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Zahtevek je posodobljen</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Zahtevek Äaka</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Å ifriranje ni možno</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Interna strežniÅ¡ka napaka</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Ni implementirano</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>NapaÄen prehod</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Storitev ni na voljo</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>ÄŒasovna omejitev strežnika</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>RazliÄica ni podprta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>SporoÄilo je preveliko</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Napaka zaradi predpogojev</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Vse je zasedeno</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Zavrnjen klic</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>Nikjer ne obstaja</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>Ni sprejemljivo kjerkoli</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Skrij ogled pogovora</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Ustvari video klic</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Pokaži razpoložljive vstavke</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Ustvari zvoÄni klic</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Dodaj k pogovoru</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Odblokiraj stik</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>PoÅ¡lji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>Možnosti</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Premaknite se na konec pogovora</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>PoÅ¡lji datoteko</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Dodaj emoji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Pusti video sporoÄilo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Pusti zvoÄno sporoÄilo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Kopiraj med prenose</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>PiÅ¡i stiku {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>vam je poslal(a) zahtevo za pogovor.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Pozdravljeni, se želite pridružiti pogovoru?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Sprejeli ste zahtevo za pogovor.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>ÄŒakamo, da druga naprava sinhronizira pogovor.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Sprejmi</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Zavrni</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>Stika ni mogoÄe vzpostaviti</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>ÄŒakanje na stik</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>Dohodni prenos</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>ÄŒas Äakanja na stik je pretekel</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Blokiraj</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Opomba: interakcija bo ustvarila nov stik.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>med vaÅ¡imi stiki</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Opomba: s poÅ¡iljanjem sporoÄila lahko samodejno sprejmete to povabilo.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>pred {0} dnevi</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>pred {0} urami</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>pred {0} minutami</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Preklicano</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>V teku</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>Pred %d dnevi</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>Pred %d ur(ami)</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>Pred %d minutami</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>pred enim dnevom</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>pred eno uro</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>ravnokar</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Ni uspelo</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>PobriÅ¡i</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Poskusi znova</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Iskanje</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>NapaÄen ID</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>UporabniÅ¡kega imena ni mogoÄe najti</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>Nisem mogel pridobiti...</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>NapaÄna shema URI</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_sq_AL.ts b/translations/lrc_sq_AL.ts new file mode 100644 index 0000000000000000000000000000000000000000..180104994dd329d6431c873776c5e30223196f29 --- /dev/null +++ b/translations/lrc_sq_AL.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="sq_AL" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Unë</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Mbaje</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Po bisedohet</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>GABIM</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Ardhëse</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Po thirret</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Po lidhet</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Po kërkohet</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Jo aktiv</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Përfundoi</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Mbarim Kohe</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Ana tjetër e zënë</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Komunikimi u vendos</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Ftesa u mor</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Kontakti u shtua</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation>%1 u ftua të vijë</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 u bashkua</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 iku</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation>%1 u përzu</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation>%1 u rishtua</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Thirrje për</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Thirrje ardhëse</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Thirrje ikse të humbura</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Thirrje ardhëse të humbura</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Ftesa u pranua</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>parazgjedhja</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Po provohet</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Po i bihet ziles</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>Po Përcillet</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>Në Radhë</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>Ecuri</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Në rregull</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>E pranuar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Zgjedhje të Shumta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Lëvizur Përgjithmonë</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Lëvizur Përkohësisht</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Përdor Ndërmjetës</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Shërbim Alternativ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Kërkesë e Gabuar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>E paautorizuar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Lypset Pagesë</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>E ndaluar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>S’u Gjet</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Metodë e Palejuar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>E papranueshme</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Lypset Mirëfilltësim Ndërmjetësi</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Mbarim Kohe për Kërkesën</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>U avullua</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Njësi Kërkese Shumë e Gjatë</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>URI Kërkese Shumë i Gjatë</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Lloj Media i Pambuluar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Skemë URI e Pambuluar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Zgjatim i Gabuar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Zgjatim i Domosdoshëm</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Kohëmatës Sesioni Shumë i Vogël</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Interval Shumë i Shkurtër</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Përkohësisht Jo i Passhëm</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>S’ekziston TSX Thirrjeje</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>U pikas Qerthull</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Shumë Kërcime</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Adresë e Paplotë</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>E dykuptimtë</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>I zënë</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Kërkesa u Përfundua</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Akt i Gabuar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Kërkesa u Përditësua</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Kërkesë Pezull</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>E padeshifrueshme</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Gabim i Brendshëm Shërbyesi</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>E pasendërtuar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Kanal i Gabuar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Shërbim i Pakapshëm</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Mbarim Kohe Shërbyesi</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Version i Pambuluar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Mesazh Shumë i Gjatë</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Dështim Parakushti</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Ngado i Zënë</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Thirrje e Hedhur Poshtë</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>S’ekziston Gjëkundi</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>E papranuar Gjëkundi</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Fshihe pamjen fjalosje</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Bëni një thirrje video</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Shfaq shtojcat e gatshme</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Bëni një thirrje audio</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Shtoje te biseda</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Hiqja dëbimin kontaktit</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Dërgoje</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>Mundësi</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Hidhu te më i riu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Dërgo kartelë</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Shtoni emoji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Lini mesazh video</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Lini mesazh audio</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Kopjo te shkarkimet</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>Shkruaje te {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>ju ka dërguar një kërkesë bisede.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Tungjatjeta, doni të merrni pjesë te biseda?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Keni pranuar kërkesën për bisedë.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>Po prisni që biseda të njëkohësohet në një tjetër pajisje.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Pranoje</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Hidhe tej</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>S’arrihet të vendoset kontakt</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>Po pritet për kontakt</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>Shpërngulje ardhëse</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>Mbaroi koha duke pritur për kontakt</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Bllokoje</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Shënim: një ndërveprim do të krijojë një kontakt të ri.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>s’gjendet në kontaktet tuaja</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Shënim: mund ta pranoni automatikisht këtë ftesë duke dërguar një mesazh.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>{0} ditë më parë</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>{0} orë më parë</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>{0} minuta më parë</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>U anulua</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>Në punë e sipër</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>%d ditë më parë</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>%d orë më parë </translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>%d minuta më parë</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>një ditë më parë</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>një orë më parë</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>mu tani</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Dështim</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Fshije</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Riprovoni</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Po kërkohet…</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>ID e pavlefshme</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>S’u gjet emër përdoruesi</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>S’u kërkua dot…</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Skemë URI i gabuar</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_sr.ts b/translations/lrc_sr.ts new file mode 100644 index 0000000000000000000000000000000000000000..caf65487700848e721d4b2946d699ba7b91752ab --- /dev/null +++ b/translations/lrc_sr.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="sr" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Povezivanje</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Primljen poziv</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Kontakt dodat</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>Korisnik %1 se pridružio</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 je napustio/la</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Poziva se</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Dolazeći poziv</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>PropuÅ¡ten odlazeći poziv</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>PropuÅ¡ten dolazeći poziv</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>podrazumevano</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>U redu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>PoÅ¡alji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Pomerite se na kraj razgovora</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>PoÅ¡alji podatak</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Prihvati</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Odbij</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Blokiraj</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Otkazan</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>IzbriÅ¡i</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_sr@Cyrl.ts b/translations/lrc_sr@Cyrl.ts new file mode 100644 index 0000000000000000000000000000000000000000..b6d132db7d461cc543136ce773bd1cb988b5cc23 --- /dev/null +++ b/translations/lrc_sr@Cyrl.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="sr@Cyrl" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Povezivanje</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Primljen poziv</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Kontakt dodat</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 Ñе придружио</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 је напуÑтио/ла</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Poziva se</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Dolazeći poziv</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>PropuÅ¡ten odlazeći poziv</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>PropuÅ¡ten dolazeći poziv</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>podrazumevano</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>U redu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>PoÅ¡alji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Pomerite se na kraj razgovora</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>PoÅ¡alji podatak</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Prihvati</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Odbij</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Blokiraj</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Otkazan</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>IzbriÅ¡i</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_sr@latin.ts b/translations/lrc_sr@latin.ts new file mode 100644 index 0000000000000000000000000000000000000000..86ca96a2fc4eecca0a70c75b052de684d1c1428b --- /dev/null +++ b/translations/lrc_sr@latin.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="sr@latin" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>Korisnik %1 se pridružio</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 je napustio/la</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_sr_RS.ts b/translations/lrc_sr_RS.ts new file mode 100644 index 0000000000000000000000000000000000000000..212602bd3404781d421d96b36b1bf23200cbcd75 --- /dev/null +++ b/translations/lrc_sr_RS.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="sr_RS" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Povezivanje</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Primljen poziv</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Kontakt dodat</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>Korisnik %1 se pridružio</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 je napustio/la</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Poziva se</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Dolazeći poziv</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>PropuÅ¡ten odlazeći poziv</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>PropuÅ¡ten dolazeći poziv</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>podrazumevano</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>U redu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>PoÅ¡alji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Pomerite se na kraj razgovora</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>PoÅ¡alji podatak</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Prihvati</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Odbij</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Blokiraj</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Otkazan</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>IzbriÅ¡i</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_sv.ts b/translations/lrc_sv.ts new file mode 100644 index 0000000000000000000000000000000000000000..50a7cde33f0f0fba5cc7ce1f2d1f84f93d92c68b --- /dev/null +++ b/translations/lrc_sv.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="sv" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Jag</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Parkera</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>Talar</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>FEL</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Inkommande</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Ringer</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>Ansluter</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Söker</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Inaktiv</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Slutförd</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Tidsgräns uppnÃ¥dd</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>Användare upptagen</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Kommunikation etablerad</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Inbjudan mottagen</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Kontakt tillagt</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation>%1 inbjöds delta</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 har gÃ¥tt med</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 har lämnat</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation>%1 slängdes ut</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation>%1 lades till </translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation>Svärm skapad </translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>UtgÃ¥ende samtal</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Inkommande samtal</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Missat utgÃ¥ende samtal</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Missat inkommande samtal</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Inbjudan accepterad</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>standard</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Null</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Försöker</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Ringer</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>Vidarebefordras</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>Köat</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>Framsteg</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>OK</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Accepterat</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Flera val</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Permanent flyttad</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>TIllfälligt flyttad</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Använd proxy</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Alternativ tjänst</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>DÃ¥lig förfrÃ¥gan</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>Obehörig</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Betalning krävs</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Förbjuden</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Kunde inte hittas</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Metod är inte tillÃ¥ten</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>Inte acceptabelt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Proxyautentisering krävs</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Tidsgräns för begäran överskriden</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>Borta</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Begärd enhet är för stor</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>Begäran URI är för lÃ¥ng</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Mediatyp som inte stöds</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>URL schema stöds ej </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Felaktigt tillägg </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Tillägg krävs</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Sessionstiden är för kort</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Intervallet är för kort</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Tillfälligt otillgänglig</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>TSX samtalet existerar inte </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Loop upptäckt </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>För mÃ¥nga hopp</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Adress inkompatibel</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>Tvetydig</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>Upptagen</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Begäran avslutad </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Misslyckat försök </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Begäran uppdaterad</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Begäran väntar</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Otydlig</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>Internt serverfel</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Inte implementerat</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>DÃ¥lig Gateway</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Tjänst ej tillgänglig</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Tidsfel server </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Version stöds inte</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Meddelandet är för stort</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Förutsättningar felaktiga</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Upptagen överallt</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Samtal vägrat</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>Finns inte nÃ¥gonstans</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>Inte acceptabelt nÃ¥gonstans</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Dölj chattvyn</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Placera videosamtal</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Visa tillgängliga tillägg </translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Placera röstsamtal</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Lägg till i konversationer</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Avblockera kontakt</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Skicka</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>Alternativ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Rulla till slutet av konversationen</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Skicka fil</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Lägg till emoji</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Lämna videomeddelande</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Lämna ljudmeddelande</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Kopiera till nedladdningar </translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>Skriv till {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>har skickat konversationsförfrÃ¥gan </translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Hej! Vill du gÃ¥ med i konversationen? </translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Du har accepterat konversationsförfrÃ¥gan.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>Vi inväntar en annan enhet att synkronisera konversationen. </translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Acceptera</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Neka</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>Ej möjligt fÃ¥ kontakt </translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>Inväntar kontakt </translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>Inkommande överföring</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>Tidsfel inväntar kontakt</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Blockera</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Notera att interaktion kommer att skapa en ny kontakt.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>finns inte i dina kontakter</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Notera att du kan acceptera denna inbjudan automatiskt, genom att skicka ett meddelande.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>{0} dagar sedan</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>{0} timmar sedan</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>{0} minuter sedan</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Avbruten</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>PÃ¥gÃ¥ende</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>%d dagar sedan</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>%d timmar sedan</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>%d minuter sedan</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>en dag sedan</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>en timma sedan</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>just nu</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Fel</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Ta bort</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Försök igen</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Söker...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>Ogiltigt ID</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Användarnamnet hittades inte</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>Kunde inte hitta...</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Felaktigt URI-schema</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_sw.ts b/translations/lrc_sw.ts new file mode 100644 index 0000000000000000000000000000000000000000..dbd8b56120a1c5170848714c80adfa5c94772f00 --- /dev/null +++ b/translations/lrc_sw.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="sw" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 amejiunga</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 imetoka nje</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>chaguo-msingi</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Sawa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Imeghairiwa</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_ta.ts b/translations/lrc_ta.ts new file mode 100644 index 0000000000000000000000000000000000000000..c84a434d03010c278948d1a70a97172596c6716b --- /dev/null +++ b/translations/lrc_ta.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="ta" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 இணைநà¯à®¤à¯à®³à¯à®³à®¾à®°à¯</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 வெளியேறியதà¯</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>இயலà¯à®ªà¯à®¨à®¿à®²à¯ˆ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>சரி</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>உரையாடலின௠மà¯à®Ÿà®¿à®µà¯à®•à¯à®•à¯ ஸà¯à®•à¯à®°à¯‹à®²à¯ செயà¯à®¯à®µà¯à®®à¯</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>கோபà¯à®ªà¯ˆ அனà¯à®ªà¯à®ªà¯</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>ரதà¯à®¤à¯ செயà¯à®¯à®ªà¯à®ªà®Ÿà¯à®Ÿà®¤à¯</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_te.ts b/translations/lrc_te.ts new file mode 100644 index 0000000000000000000000000000000000000000..49c96a482441408ab6765e1878b80e7045acdd7d --- /dev/null +++ b/translations/lrc_te.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="te" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 చేరారà±</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 నిషà±à°•à±à°°à°®à°¿à°‚చారà±</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>డిఫాలà±à°Ÿà±</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>సరే</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>సంà°à°¾à°·à°£ à°®à±à°—à°¿à°‚à°ªà±à°²à±‹à°•à°¿ à°¸à±à°•à±à°°à±‹à°²à± చేయండి</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>ఫైలà±â€Œà°¨à°¿ పంపà±</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>à°°à°¦à±à°¦à± చేయబడినది</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_th.ts b/translations/lrc_th.ts new file mode 100644 index 0000000000000000000000000000000000000000..c0d81ba518cf8f0351020226fbf59332be184c5e --- /dev/null +++ b/translations/lrc_th.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="th" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 เข้าร่วมà¹à¸¥à¹‰à¸§</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 à¸à¸à¸à¹„ปà¹à¸¥à¹‰à¸§</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>ค่าเริ่มต้น</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>ตà¸à¸¥à¸‡</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>เลื่à¸à¸™à¹„ปยังจุดสิ้นสุดขà¸à¸‡à¸à¸²à¸£à¸ªà¸™à¸—นา</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>ส่งไฟล์</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>ยà¸à¹€à¸¥à¸´à¸à¹à¸¥à¹‰à¸§</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_tr.ts b/translations/lrc_tr.ts new file mode 100644 index 0000000000000000000000000000000000000000..7aca7fc6d3b47957e4ef7a89e8a86c91157154bf --- /dev/null +++ b/translations/lrc_tr.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="tr" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Ben</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Beklet</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>KonuÅŸuyor</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>HATA</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Gelen</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Aranıyor</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>BaÄŸlanılıyor</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Arama yapılıyor</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>Etkisiz</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>Bitti</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>Zamanaşımı</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>EÅŸ meÅŸgul</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>BaÄŸlantı saÄŸlandı</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Davetiye alındı</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>KiÅŸi eklendi</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation>%1 katılmaya davet edildi</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 katıldı</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 çıkış yapıldı</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation>%1 atıldı</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation>%1 tekrar eklendi</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation>Küme oluÅŸturuldu</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Giden arama</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Gelen arama</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Yanıtsız giden arama</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Yanıtsız gelen arama</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>Davetiye alındı</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>varsayılan</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>BoÅŸ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>Deneniyor</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Çalıyor</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>Yönlendiriliyor</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>Sırada</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>Ä°lerleme</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Tamam</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>Kabul edildi</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>Çoklu Seçimler</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>Kalıcı Olarak Taşındı</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>Geçici Olarak Taşındı</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>Vekil Kullan</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>Alternatif servis</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>Geçersiz istek</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>YetkilendirilmemiÅŸ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>Ödeme Gerekli</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>Yasak</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>Bulunamadı</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>Metod Kabul Edilmiyor</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>Kabul Edilemez</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>Proxy Kimlik DoÄŸrulaması Gerekiyor</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>Ä°stek Zaman Aşımına UÄŸradı</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>GitmiÅŸ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>Girilen veri çok fazla</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>URI Ä°steÄŸi Çok Uzun</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>Desteklenmeyen Ortam Türü</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>Desteklenmeyen URI Düzeni</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>Hatalı Uzantı</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>Uzantı Gerekli</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>Oturum Zamanlayıcısı Çok Küçük</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>Aralık Çok Kısa</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>Geçici olarak kullanım dışı</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>TSX ÇaÄŸrısı Yok</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>Döngü Algılandı</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>Çok Fazla Atlama</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>Adres Eksik</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>Belirsiz</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>MeÅŸgul</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>Ä°stek Sonlandırıldı</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>Kötü Etkinlik</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>Ä°stek Güncellendi</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>Ä°stek Beklemede</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>Anlaşılamaz</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>İç Sunucu Hatası</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>Uygulanmadı</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>Bozuk AÄŸ Geçidi</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>Hizmet kullanılamıyor</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>Sunucu Zaman Aşımı</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>Sürüm Desteklenmiyor</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>Mesaj Çok Büyük</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>Ön KoÅŸul Hatası</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>Her Yerde MeÅŸgul</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>Arama reddedildi</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>Herhangi Bir Yerde Yok</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>Hiçbir Yerde Kabul Edilemez</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>KonuÅŸma görünümünü gizle</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Görüntülü arama yeri</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>Kullanılabilir eklentileri göster</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Sesli arama yeri </translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>KonuÅŸma ekle</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>KiÅŸinin engelini kaldır</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Gönder</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>Seçenekler</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Görüşmenin sonuna kaydır</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Dosya gönder</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>Emoji ekle</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>Görüntülü ileti bırak</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>Sesli mesaj bırak</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>Ä°ndirilenlere kopyala</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>{0} 'a yaz</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>size bir görüşme isteÄŸi gönderdi.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>Ä°yi günler, görüşmeye katılmak ister misiniz?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>Görüşme isteÄŸini kabul ettiniz.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>BaÅŸka bir aygıtın bu konuÅŸmayı senkronize etmesi bekleniyor</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>Kabul et</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>Geri Çevir</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>Ä°letiÅŸim kurulamadı</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>Ä°letiÅŸim bekleniyor</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>Gelen aktarım</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>Ä°letiÅŸim zaman aşımına uÄŸradı</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Engelleme</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>No: etkileÅŸim yeni bir kiÅŸi oluÅŸturacaktır.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>kiÅŸilerinizde yok</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Anımsatma: ileti göndererek bu davetiyeyi kendiliÄŸinden kabul edebilirsiniz.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>{0} gün önce</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>{0} saat önce</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>{0} dakika önce</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Ä°ptal edildi</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>Devam Ediyor</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>%d gün önce</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>%d saat önce</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>%d dakika önce</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>bir gün önce</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>bir saat önce</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>Åžu an</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>BaÅŸarısız</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Sil</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Yeniden dene</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>Arıyor...</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>Geçersiz kimlik</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>Kullanıcı adı bulunamadı</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>Arama yapılamadı…</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>Hatalı URI ÅŸeması</translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_tr_TR.ts b/translations/lrc_tr_TR.ts new file mode 100644 index 0000000000000000000000000000000000000000..5a651876bbc50fbe59663328dcc22b5aa71976a9 --- /dev/null +++ b/translations/lrc_tr_TR.ts @@ -0,0 +1,619 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS language="tr_TR" sourcelanguage="en" version="2.1"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="328"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="130"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="898"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="127"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="896"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="104"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="110"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="894"/> + <source>Outgoing call</source> + <translation>Giden arama</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="106"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="116"/> + <source>Incoming call</source> + <translation>Gelen arama</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="112"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="892"/> + <source>Missed outgoing call</source> + <translation>Giden cevapsız çaÄŸrı</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="118"/> + <source>Missed incoming call</source> + <translation>Gelen cevapsız çaÄŸrı</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="132"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="900"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="335"/> + <location filename="../src/libclient/avmodel.cpp" line="354"/> + <source>default</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="53"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="54"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="55"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="56"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="57"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="58"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="59"/> + <source>OK</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="46"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="49"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="51"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="53"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>Canceled</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="51"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="53"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="55"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="57"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Confirm</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>Deny</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="61"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="459"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="955"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="958"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="961"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="420"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_tt.ts b/translations/lrc_tt.ts new file mode 100644 index 0000000000000000000000000000000000000000..c02d3db601a5f50ff108bbb60b3e98dbabc769b8 --- /dev/null +++ b/translations/lrc_tt.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="tt" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 кушылган</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 чыкты</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>Килешенгәнчә</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Хуп</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Файлларны җибәрү</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Баш тартты</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_uk.ts b/translations/lrc_uk.ts new file mode 100644 index 0000000000000000000000000000000000000000..cce421d18cf1e5a90237af9cafc1c980ceb98c11 --- /dev/null +++ b/translations/lrc_uk.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="uk" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>Я</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>Режим очікуваннÑ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>РозмовлÑÑ”</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>ПОМИЛКÐ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>Викликає</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>Дзвінок</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>З'єднаннÑ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>Шукаю</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>Зв’Ñзок вÑтановлено</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>Отримано запрошеннÑ</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>Контакт додано</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 приєднуєтьÑÑ</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>КориÑтувач %1 вийшов</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>Вихідний виклик</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>Вхідний виклик</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>Пропущений вихідний виклик</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>Пропущений вхідний виклик</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>за замовчуваннÑм</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>Дзвінок</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Гаразд</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>ÐžÑ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ñ–ÑÐ»Ñ Ð·Ð°Ð¿Ñ€Ð¾Ñу</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>ЗайнÑтий</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>Сховати вікно чату</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>Почати відео дзвінок</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>Почати аудіо дзвінок</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>Додати до розмови</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>Розблокувати контакт</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>Відправити</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Прокрутити до ÐºÑ–Ð½Ñ†Ñ Ñ€Ð¾Ð·Ð¼Ð¾Ð²Ð¸</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Відправити файл</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>ПрийнÑти</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>СкиданнÑ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>Заблокувати</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>Зверніть увагу: Ð²Ð·Ð°Ñ”Ð¼Ð¾Ð´Ñ–Ñ Ñтворить новий контакт</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>Зважте: ви можете автоматично прийнÑти це запрошеннÑ, направивши повідомленнÑ.</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>СкаÑовано</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>%d днів тому</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>%d годин тому</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>%d хвилин тому</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>один день тому</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>одну годину тому</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>щойно</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>Ðевдача</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>Видалити</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>Спробувати ще</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_uk_UA.ts b/translations/lrc_uk_UA.ts new file mode 100644 index 0000000000000000000000000000000000000000..c22db42f3a54f26a8a55d85608d7c6d850ba9d42 --- /dev/null +++ b/translations/lrc_uk_UA.ts @@ -0,0 +1,578 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS language="uk_UA" sourcelanguage="en" version="2.1"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="328"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="130"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="898"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="127"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="896"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="104"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="110"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="894"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="106"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="116"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="112"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="892"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="118"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="132"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="900"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="330"/> + <location filename="../src/libclient/avmodel.cpp" line="349"/> + <source>default</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="53"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="54"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="55"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="56"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="57"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="58"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="59"/> + <source>OK</source> + <translation>OK</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Jump to latest</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Send file</source> + <translation>Відправити файл</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Type a message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="46"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="49"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="51"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="53"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="51"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="53"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="55"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="57"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="61"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="455"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="950"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="953"/> + <source>Registered name not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="956"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="419"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_vi.ts b/translations/lrc_vi.ts new file mode 100644 index 0000000000000000000000000000000000000000..c42359e213e94dbe7576e9027ac80a2c966695ba --- /dev/null +++ b/translations/lrc_vi.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="vi" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 đã tham gia</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 Ä‘ã rÆ¡Ì€i khỏi</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>mặc định</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>Äược rồi</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>Cuá»™n đến cuối cuá»™c há»™i thoại</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>Gá»i táºp tin</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>Äã hủy bá»</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation type="unfinished"/> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation type="unfinished"/> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation type="unfinished"/> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_zh.ts b/translations/lrc_zh.ts new file mode 100644 index 0000000000000000000000000000000000000000..4ae4c09d540884c47dcbeea7ccd4671ecb2b14d4 --- /dev/null +++ b/translations/lrc_zh.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="zh" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>我</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>ä¿æŒé€šè©±</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>æ£åœ¨é€šè¯</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>错误</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>æ¥ç”µ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>撥打</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>連接ä¸</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>æ£åœ¨æœç´¢</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>ä¸æ´»è·ƒ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>å·²çµæŸ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>超时</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>对ç‰èŠ‚点忙</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>通信已建立</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>已接å—邀请</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>å·²åŠ å…¥é€šè®¯å½•</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation>%1 å·²è¢«é‚€è«‹åŠ å…¥</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1å·²åŠ å…¥</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 已離開</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation>%1 已踢除</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation>%1 å·²é‡æ–°æ–°å¢ž</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation>已建立 Swarm</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>撥出電話</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>來電</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>未接去電</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>未接來電</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>已接å—邀请</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>默认</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>æ— æ•ˆ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>æ£åœ¨å°è¯•</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>響鈴ä¸</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>æ£åœ¨è½¬æŽ¥</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>排队ä¸</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>进度</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>確定</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>已接å—</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>多选</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>永久移动 </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>暂时移动 </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>使用代ç†</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>替代æœåŠ¡ </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>ä¸å¯ç”¨çš„请求</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>未授æƒçš„</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>需è¦ä»˜æ¬¾</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>ç¦æ¢çš„</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>未找到</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>æ–¹å¼ä¸å…许</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>ä¸å¯æŽ¥å—</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>需è¦ä»£ç†æœåŠ¡å™¨è®¤è¯</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>請求逾時</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>已离开</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>请求的实体太大</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>请求的 URI 太长</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>ä¸æ”¯æŒçš„媒体类型</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>ä¸å—支æŒçš„ URI 方案</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>错误的扩展å </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>需è¦æ‰©å±•å</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>会è¯è®¡æ—¶å™¨å¤ªå° </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>é—´éš”å¤ªçŸ </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>æš‚æ—¶ä¸å¯ç”¨ </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>Call TSX ä¸å˜åœ¨</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>检测到环路</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>跳数太多</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>地å€ä¸å®Œæ•´ </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>å«ç³Š</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>忙碌</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>è¯·æ±‚ç»ˆæ¢ </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>ä¸è‰¯äº‹ä»¶ </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>请求已更新</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>è¯·æ±‚å¾…å¤„ç† </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>æ— æ³•è§£ç </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>内部æœåŠ¡å™¨é”™è¯¯ </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>未实现 </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>æ— æ•ˆç½‘å…³</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>æœåŠ¡ä¸å¯ç”¨</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>æœåŠ¡å™¨è¶…æ—¶</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>ä¸æ”¯æŒçš„版本 </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>消æ¯å°ºå¯¸å¤ªå¤§</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>å‰ææ¡ä»¶å¤±è´¥</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>æœåŠ¡å™¨ç¹å¿™</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>呼å«è¢«æ‹’</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>任何地方都ä¸å˜åœ¨ </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>任何地方都ä¸å¯æŽ¥å—</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>éšè—èŠå¤©ç•Œé¢</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>å‘起视频通è¯</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>显示å¯ç”¨æ’件</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>開始語音通話</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>新增到å°è©±ä¸</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>å–消å°éŽ–è¯çµ¡äºº</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>發é€</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>é¸é …</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>跳到最新</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>å‘é€æ–‡ä»¶</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>æ·»åŠ è¡¨æƒ…</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>视频留言</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>音频留言</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>å¤åˆ¶åˆ°ä¸‹è½½</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>写给 {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>å‘您å‘é€äº†ä¼šè¯è¯·æ±‚。</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>您好,è¦åŠ 入会è¯å—?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>您已接å—会è¯è¯·æ±‚。</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>æ£åœ¨ç‰å¾…å¦ä¸€ä¸ªè®¾å¤‡åŒæ¥ä¼šè¯ã€‚</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>接收</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>拒絕</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>ç„¡æ³•åŠ ç‚ºè¯çµ¡äºº</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>ç‰å¾…è¯çµ¡äºº</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>å…¥ç«™ä¼ é€</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>ç‰å¾…è”系人超时</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>å±è”½</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>注:交互将创建一个新的è”系人。</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>ä¸åœ¨æ‚¨çš„通訊錄ä¸</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>注:您å¯ä»¥é€šè¿‡å‘é€æ¶ˆæ¯è‡ªåŠ¨æŽ¥å—æ¤é‚€è¯·ã€‚</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>{0} 天å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>{0} å°æ™‚å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>{0} 分é˜å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>å·²å–消</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>æ£åœ¨è¿›è¡Œ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>%d天å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>%då°æ—¶å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>%d分钟å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>一天å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>一å°æ—¶å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>刚æ‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>失败</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>刪除</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>é‡è¯•</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>æ£åœ¨æœç´¢â€¦</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>éžæ³• ID</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>未找到用户å</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>æ— æ³•æŸ¥æ‰¾...</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>错误的 URI 方案 </translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_zh_CN.ts b/translations/lrc_zh_CN.ts new file mode 100644 index 0000000000000000000000000000000000000000..c8a8d82ee9095426689068cd6fcbac8393c4fcdd --- /dev/null +++ b/translations/lrc_zh_CN.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="zh_CN" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>我</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>ç‰å¾…</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>æ£åœ¨é€šè¯</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>错误</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>æ¥ç”µ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>æ£åœ¨é€šè¯</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>æ£åœ¨è¿žæŽ¥</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>æ£åœ¨æœç´¢</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>ä¸æ´»è·ƒ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>完æˆ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>超时</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>对ç‰èŠ‚点忙</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>通信已建立</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>已接å—邀请</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>å·²åŠ å…¥é€šè®¯å½•</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation>%1 å·²è¢«é‚€è«‹åŠ å…¥</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1å·²åŠ å…¥</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 已離開</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation>%1 已踢除</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation>%1 å·²é‡æ–°æ–°å¢ž</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation>已建立 Swarm</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>去电</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>æ¥ç”µ</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>去电未接</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>未接æ¥ç”µ</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>已接å—邀请</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>默认</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>æ— æ•ˆ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>æ£åœ¨å°è¯•</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>æ£åœ¨å‘¼å«</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>æ£åœ¨è½¬æŽ¥</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>排队ä¸</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>进度</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>确定</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>已接å—</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>多选</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>永久移动 </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>暂时移动 </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>使用代ç†</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>替代æœåŠ¡ </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>ä¸å¯ç”¨çš„请求</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>未授æƒçš„</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>需è¦ä»˜æ¬¾</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>ç¦æ¢çš„</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>未找到</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>æ–¹å¼ä¸å…许</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>ä¸å¯æŽ¥å—</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>需è¦ä»£ç†æœåŠ¡å™¨è®¤è¯</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>请求超时</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>已离开</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>请求的实体太大</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>请求的 URI 太长</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>ä¸æ”¯æŒçš„媒体类型</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>ä¸å—支æŒçš„ URI 方案</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>错误的扩展å </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>需è¦æ‰©å±•å</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>会è¯è®¡æ—¶å™¨å¤ªå° </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>é—´éš”å¤ªçŸ </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>æš‚æ—¶ä¸å¯ç”¨ </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>Call TSX ä¸å˜åœ¨</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>检测到环路</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>跳数太多</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>地å€ä¸å®Œæ•´ </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>å«ç³Š</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>忙碌</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>è¯·æ±‚ç»ˆæ¢ </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>ä¸è‰¯äº‹ä»¶ </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>请求已更新</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>è¯·æ±‚å¾…å¤„ç† </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>æ— æ³•è§£ç </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>内部æœåŠ¡å™¨é”™è¯¯ </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>未实现 </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>æ— æ•ˆç½‘å…³</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>æœåŠ¡ä¸å¯ç”¨</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>æœåŠ¡å™¨è¶…æ—¶</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>ä¸æ”¯æŒçš„版本 </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>消æ¯å°ºå¯¸å¤ªå¤§</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>å‰ææ¡ä»¶å¤±è´¥</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>æœåŠ¡å™¨ç¹å¿™</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>呼å«è¢«æ‹’</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>任何地方都ä¸å˜åœ¨ </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>任何地方都ä¸å¯æŽ¥å—</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>éšè—èŠå¤©ç•Œé¢</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>å‘起视频通è¯</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>显示å¯ç”¨æ’件</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>å‘èµ·è¯éŸ³é€šè¯</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>æ·»åŠ åˆ°ä¼šè¯</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>å–消å±è”½è”系人</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>å‘é€</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>选项</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>跳转至最新</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>å‘é€æ–‡ä»¶</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>æ·»åŠ è¡¨æƒ…</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>视频留言</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>音频留言</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>å¤åˆ¶åˆ°ä¸‹è½½</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>写给 {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>å‘您å‘é€äº†ä¼šè¯è¯·æ±‚。</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>您好,è¦åŠ 入会è¯å—?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>您已接å—会è¯è¯·æ±‚。</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>æ£åœ¨ç‰å¾…å¦ä¸€ä¸ªè®¾å¤‡åŒæ¥ä¼šè¯ã€‚</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>接收</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>拒接</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>æ— æ³•è”ç³»</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>æ£åœ¨ç‰å¾…è”系人</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>å…¥ç«™ä¼ é€</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>ç‰å¾…è”系人超时</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>å±è”½</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>注:交互将创建一个新的è”系人。</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>ä¸æ˜¯æ‚¨çš„è”系人</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>注:您å¯ä»¥é€šè¿‡å‘é€æ¶ˆæ¯è‡ªåŠ¨æŽ¥å—æ¤é‚€è¯·ã€‚</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>{0} 天å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>{0} å°æ—¶å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>{0} 分钟å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>å·²å–消</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>æ£åœ¨è¿›è¡Œ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>%d天å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>%då°æ—¶å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>%d分钟å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>一天å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>一å°æ—¶å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>刚æ‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>失败</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>åˆ é™¤</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>é‡è¯•</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>æ£åœ¨æœç´¢â€¦</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>éžæ³• ID</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>未找到用户å</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>æ— æ³•æŸ¥æ‰¾...</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>错误的 URI 方案 </translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_zh_HK.ts b/translations/lrc_zh_HK.ts new file mode 100644 index 0000000000000000000000000000000000000000..8f3f84d8287e07bcf105f6e38c5fae7099440a83 --- /dev/null +++ b/translations/lrc_zh_HK.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="zh_HK" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>我</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>æš«åœé€šè©±</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>æ£åœ¨é€šè¯</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>错误</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>æ¥ç”µ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>撥打</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>連接ä¸</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>æ£åœ¨æœç´¢</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>ä¸æ´»è·ƒ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>å·²çµæŸ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>超时</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>对ç‰èŠ‚点忙</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>通信已建立</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>已接å—邀请</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>å·²åŠ å…¥é€šè®¯å½•</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation>%1 å·²è¢«é‚€è«‹åŠ å…¥</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 å·²åŠ å…¥</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 已離開</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation>%1 已踢除</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation>%1 å·²é‡æ–°æ–°å¢ž</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation>已建立 Swarm</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>撥出電話</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>æ¥ç”µ</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>未接去電</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>未接來電</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>已接å—邀请</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>é è¨</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>æ— æ•ˆ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>æ£åœ¨å°è¯•</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>響鈴ä¸</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>æ£åœ¨è½¬æŽ¥</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>排队ä¸</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>进度</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>確定</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>已接å—</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>多选</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>永久移动 </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>暂时移动 </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>使用代ç†</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>替代æœåŠ¡ </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>ä¸å¯ç”¨çš„请求</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>未授æƒçš„</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>需è¦ä»˜æ¬¾</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>ç¦æ¢çš„</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>未找到</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>æ–¹å¼ä¸å…许</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>ä¸å¯æŽ¥å—</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>需è¦ä»£ç†æœåŠ¡å™¨è®¤è¯</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>請求逾時</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>已离开</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>请求的实体太大</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>请求的 URI 太长</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>ä¸æ”¯æŒçš„媒体类型</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>ä¸å—支æŒçš„ URI 方案</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>错误的扩展å </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>需è¦æ‰©å±•å</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>会è¯è®¡æ—¶å™¨å¤ªå° </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>é—´éš”å¤ªçŸ </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>æš‚æ—¶ä¸å¯ç”¨ </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>Call TSX ä¸å˜åœ¨</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>检测到环路</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>跳数太多</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>地å€ä¸å®Œæ•´ </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>å«ç³Š</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>忙碌</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>è¯·æ±‚ç»ˆæ¢ </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>ä¸è‰¯äº‹ä»¶ </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>请求已更新</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>è¯·æ±‚å¾…å¤„ç† </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>æ— æ³•è§£ç </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>内部æœåŠ¡å™¨é”™è¯¯ </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>未实现 </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>æ— æ•ˆç½‘å…³</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>æœåŠ¡ä¸å¯ç”¨</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>æœåŠ¡å™¨è¶…æ—¶</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>ä¸æ”¯æŒçš„版本 </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>消æ¯å°ºå¯¸å¤ªå¤§</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>å‰ææ¡ä»¶å¤±è´¥</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>æœåŠ¡å™¨ç¹å¿™</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>呼å«è¢«æ‹’</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>任何地方都ä¸å˜åœ¨ </translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>任何地方都ä¸å¯æŽ¥å—</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>éšè—èŠå¤©ç•Œé¢</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>å‘起视频通è¯</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>显示å¯ç”¨æ’件</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>開始語音通話</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>新增到å°è©±ä¸</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>å–消å°éŽ–è¯çµ¡äºº</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>å‘é€</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>é¸é …</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>跳到最新</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>傳é€æª”案</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>æ·»åŠ è¡¨æƒ…</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>视频留言</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>音频留言</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>å¤åˆ¶åˆ°ä¸‹è½½</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>写给 {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>å‘您å‘é€äº†ä¼šè¯è¯·æ±‚。</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>您好,è¦åŠ 入会è¯å—?</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>您已接å—会è¯è¯·æ±‚。</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>æ£åœ¨ç‰å¾…å¦ä¸€ä¸ªè®¾å¤‡åŒæ¥ä¼šè¯ã€‚</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>接收</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>拒接</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>ç„¡æ³•åŠ ç‚ºè¯çµ¡äºº</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>ç‰å¾…è¯çµ¡äºº</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>å…¥ç«™ä¼ é€</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>ç‰å¾…è”系人超时</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>å±è”½</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>注:交互将创建一个新的è”系人。</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>ä¸åœ¨æ‚¨çš„通訊錄ä¸</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>注:您å¯ä»¥é€šè¿‡å‘é€æ¶ˆæ¯è‡ªåŠ¨æŽ¥å—æ¤é‚€è¯·ã€‚</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>{0} 天å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>{0} å°æ™‚å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>{0} 分é˜å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>å·²å–消</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>æ£åœ¨è¿›è¡Œ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>%d天å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>%då°æ—¶å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>%d分钟å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>一天å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>一å°æ—¶å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>刚æ‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>失败</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>刪除</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>é‡è¯•</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>æ£åœ¨æœç´¢â€¦</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>éžæ³• ID</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>未找到用户å</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>æ— æ³•æŸ¥æ‰¾...</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>错误的 URI 方案 </translation> + </message> +</context> +</TS> \ No newline at end of file diff --git a/translations/lrc_zh_TW.ts b/translations/lrc_zh_TW.ts new file mode 100644 index 0000000000000000000000000000000000000000..4417e6a2a322624f162de618e1d45da49e08bf95 --- /dev/null +++ b/translations/lrc_zh_TW.ts @@ -0,0 +1,675 @@ +<?xml version="1.0" ?><!DOCTYPE TS><TS version="2.1" language="zh_TW" sourcelanguage="en"> +<context> + <name>QObject</name> + <message> + <location filename="../src/libclient/qtwrapper/callmanager_wrap.h" line="450"/> + <source>Me</source> + <translation>我</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="61"/> + <source>Hold</source> + <translation>æš«åœé€šè©±</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="63"/> + <source>Talking</source> + <translation>通話ä¸</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="65"/> + <source>ERROR</source> + <translation>錯誤</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="67"/> + <source>Incoming</source> + <translation>來電</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="69"/> + <source>Calling</source> + <translation>æ£åœ¨é€šè©±</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="71"/> + <location filename="../src/libclient/chatview.cpp" line="72"/> + <source>Connecting</source> + <translation>連接ä¸</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="73"/> + <source>Searching</source> + <translation>æœå°‹</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="75"/> + <source>Inactive</source> + <translation>ä¸æ´»èº</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="77"/> + <location filename="../src/libclient/api/call.h" line="83"/> + <location filename="../src/libclient/chatview.cpp" line="79"/> + <source>Finished</source> + <translation>å·²çµæŸ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="79"/> + <source>Timeout</source> + <translation>逾時</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="81"/> + <source>Peer busy</source> + <translation>å°æ–¹å¿™ç¢Œ</translation> + </message> + <message> + <location filename="../src/libclient/api/call.h" line="85"/> + <source>Communication established</source> + <translation>已建立通訊</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="197"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="952"/> + <source>Invitation received</source> + <translation>已收到邀請</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="224"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="194"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="950"/> + <source>Contact added</source> + <translation>已新增è¯çµ¡äºº</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="226"/> + <source>%1 was invited to join</source> + <translation>%1 å·²è¢«é‚€è«‹åŠ å…¥</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="228"/> + <source>%1 joined</source> + <translation>%1 å·²åŠ å…¥</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="230"/> + <source>%1 left</source> + <translation>%1 已離開</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="232"/> + <source>%1 was kicked</source> + <translation>%1 已踢除</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="234"/> + <source>%1 was re-added</source> + <translation>%1 å·²é‡æ–°æ–°å¢ž</translation> + </message> + <message> + <location filename="../src/libclient/api/interaction.h" line="300"/> + <source>Swarm created</source> + <translation>已建立 Swarm</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="171"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="177"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="948"/> + <source>Outgoing call</source> + <translation>撥出電話</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="173"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="183"/> + <source>Incoming call</source> + <translation>來電</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="179"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="946"/> + <source>Missed outgoing call</source> + <translation>未接去電</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="185"/> + <source>Missed incoming call</source> + <translation>未接來電</translation> + </message> + <message> + <location filename="../src/libclient/authority/storagehelper.cpp" line="199"/> + <location filename="../src/libclient/authority/storagehelper.cpp" line="954"/> + <source>Invitation accepted</source> + <translation>已接å—邀請</translation> + </message> + <message> + <location filename="../src/libclient/avmodel.cpp" line="348"/> + <location filename="../src/libclient/avmodel.cpp" line="367"/> + <source>default</source> + <translation>é è¨</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="60"/> + <source>Null</source> + <translation>Null</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="61"/> + <source>Trying</source> + <translation>æ£åœ¨å˜—試</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="62"/> + <source>Ringing</source> + <translation>響鈴ä¸</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="63"/> + <source>Being Forwarded</source> + <translation>已轉寄</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="64"/> + <source>Queued</source> + <translation>已進入佇列</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="65"/> + <source>Progress</source> + <translation>排程</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="66"/> + <source>OK</source> + <translation>確定</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="73"/> + <location filename="../src/libclient/newcallmodel.cpp" line="67"/> + <source>Accepted</source> + <translation>已接å—</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="68"/> + <source>Multiple Choices</source> + <translation>多é¸</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="69"/> + <source>Moved Permanently</source> + <translation>永久移動</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="70"/> + <source>Moved Temporarily</source> + <translation>暫時移動</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="71"/> + <source>Use Proxy</source> + <translation>使用代ç†ä¼ºæœå™¨</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="72"/> + <source>Alternative Service</source> + <translation>替代æœå‹™</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="73"/> + <source>Bad Request</source> + <translation>ä¸è‰¯çš„請求</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="74"/> + <source>Unauthorized</source> + <translation>未授權</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="75"/> + <source>Payment Required</source> + <translation>需è¦ä»˜æ¬¾</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="76"/> + <source>Forbidden</source> + <translation>被ç¦æ¢</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="77"/> + <source>Not Found</source> + <translation>找ä¸åˆ°</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="78"/> + <source>Method Not Allowed</source> + <translation>ä¸å…許的方法</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="79"/> + <location filename="../src/libclient/newcallmodel.cpp" line="99"/> + <source>Not Acceptable</source> + <translation>無法接å—</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="80"/> + <source>Proxy Authentication Required</source> + <translation>需è¦ä»£ç†ä¼ºæœå™¨é©—è‰</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="81"/> + <source>Request Timeout</source> + <translation>請求逾時</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="82"/> + <source>Gone</source> + <translation>消失</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="83"/> + <source>Request Entity Too Large</source> + <translation>請求實體太大</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="84"/> + <source>Request URI Too Long</source> + <translation>請求 URI 太長</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="85"/> + <source>Unsupported Media Type</source> + <translation>ä¸æ”¯æ´çš„媒體類型</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="86"/> + <source>Unsupported URI Scheme</source> + <translation>ä¸æ”¯æ´çš„ URI çµæ§‹</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="87"/> + <source>Bad Extension</source> + <translation>ä¸è‰¯çš„副檔å</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="88"/> + <source>Extension Required</source> + <translation>需è¦å‰¯æª”å</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="89"/> + <source>Session Timer Too Small</source> + <translation>工作階段計時器太å°äº†</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="90"/> + <source>Interval Too Brief</source> + <translation>間隔太çŸ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="91"/> + <source>Temporarily Unavailable</source> + <translation>暫時ä¸å¯ç”¨</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="92"/> + <source>Call TSX Does Not Exist</source> + <translation>å‘¼å« TSX ä¸å˜åœ¨</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="93"/> + <source>Loop Detected</source> + <translation>åµæ¸¬åˆ°è¿´åœˆ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="94"/> + <source>Too Many Hops</source> + <translation>太多跳èº</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="95"/> + <source>Address Incomplete</source> + <translation>地å€ä¸å®Œæ•´</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="96"/> + <source>Ambiguous</source> + <translation>曖昧</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="97"/> + <source>Busy</source> + <translation>忙碌</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="98"/> + <source>Request Terminated</source> + <translation>請求已終çµ</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="100"/> + <source>Bad Event</source> + <translation>ä¸è‰¯çš„活動</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="101"/> + <source>Request Updated</source> + <translation>請求已更新</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="102"/> + <source>Request Pending</source> + <translation>請求擱置</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="103"/> + <source>Undecipherable</source> + <translation>無法解密</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="104"/> + <source>Internal Server Error</source> + <translation>內部伺æœå™¨éŒ¯èª¤</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="105"/> + <source>Not Implemented</source> + <translation>未實作</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="106"/> + <source>Bad Gateway</source> + <translation>ä¸è‰¯çš„é–˜é“</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="107"/> + <source>Service Unavailable</source> + <translation>æœå‹™ä¸å¯ç”¨</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="108"/> + <source>Server Timeout</source> + <translation>伺æœå™¨é€¾æ™‚</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="109"/> + <source>Version Not Supported</source> + <translation>版本ä¸æ”¯æ´</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="110"/> + <source>Message Too Large</source> + <translation>訊æ¯å¤ªå¤§</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="111"/> + <source>Precondition Failure</source> + <translation>å‰ææ¢ä»¶å¤±æ•—</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="112"/> + <source>Busy Everywhere</source> + <translation>到處都忙碌</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="113"/> + <source>Call Refused</source> + <translation>通話被拒絕</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="114"/> + <source>Does Not Exist Anywhere</source> + <translation>到處都ä¸å˜åœ¨</translation> + </message> + <message> + <location filename="../src/libclient/newcallmodel.cpp" line="115"/> + <source>Not Acceptable Anywhere</source> + <translation>到處都ä¸æŽ¥å—</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="30"/> + <source>Hide chat view</source> + <translation>éš±è—èŠå¤©è¦–窗</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="31"/> + <source>Place video call</source> + <translation>撥出視訊通話</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="32"/> + <source>Show available plugins</source> + <translation>顯示å¯ç”¨çš„外掛程å¼</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="33"/> + <source>Place audio call</source> + <translation>開始語音通話</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="34"/> + <source>Add to conversations</source> + <translation>新增到å°è©±ä¸</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="35"/> + <source>Unban contact</source> + <translation>å–消å°éŽ–è¯çµ¡äºº</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="36"/> + <source>Send</source> + <translation>傳é€</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="37"/> + <source>Options</source> + <translation>é¸é …</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="38"/> + <source>Jump to latest</source> + <translation>跳到最新</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="39"/> + <source>Send file</source> + <translation>傳é€æª”案</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="40"/> + <source>Add emoji</source> + <translation>新增表情符號</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="41"/> + <source>Leave video message</source> + <translation>留下視訊訊æ¯</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="42"/> + <source>Leave audio message</source> + <translation>留下語音訊æ¯</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="44"/> + <source>Copy to downloads</source> + <translation>複製到下載</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="45"/> + <source>Write to {0}</source> + <translation>寫入到 {0}</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="50"/> + <source>has sent you a conversation request.</source> + <translation>å·²å‘您傳é€å°è©±è«‹æ±‚。</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="52"/> + <source>Hello, do you want to join the conversation?</source> + <translation>æ‚¨å¥½ï¼Œæ‚¨æƒ³åŠ å…¥å°è©±å—Žï¼Ÿ</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="54"/> + <source>You have accepted the conversation request.</source> + <translation>您已接å—å°è©±è«‹æ±‚。</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="56"/> + <source>We are waiting for another device to synchronize the conversation.</source> + <translation>我們æ£åœ¨ç‰å¾…其他è£ç½®åŒæ¥å°è©±ã€‚</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="67"/> + <source>Accept</source> + <translation>接è½</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="68"/> + <source>Refuse</source> + <translation>拒絕</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="71"/> + <source>Unable to make contact</source> + <translation>ç„¡æ³•åŠ ç‚ºè¯çµ¡äºº</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="76"/> + <source>Waiting for contact</source> + <translation>ç‰å¾…è¯çµ¡äºº</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="77"/> + <source>Incoming transfer</source> + <translation>來電轉發</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="78"/> + <source>Timed out waiting for contact</source> + <translation>ç‰å¾…è¯çµ¡äººé€¾æ™‚</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="43"/> + <source>Block</source> + <translation>阻擋</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="47"/> + <source>Note: an interaction will create a new contact.</source> + <translation>注æ„:互動將會建立新è¯çµ¡äººã€‚</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="48"/> + <source>is not in your contacts</source> + <translation>ä¸åœ¨æ‚¨çš„通訊錄ä¸</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="58"/> + <source>Note: you can automatically accept this invitation by sending a message.</source> + <translation>注æ„:您å¯ä»¥é€éŽå‚³é€è¨Šæ¯ä¾†è‡ªå‹•æŽ¥å—æ¤é‚€è«‹ã€‚</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>{0} days ago</source> + <translation>{0} 天å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>{0} hours ago</source> + <translation>{0} å°æ™‚å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>{0} minutes ago</source> + <translation>{0} 分é˜å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="74"/> + <source>Canceled</source> + <translation>å·²å–消</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="75"/> + <source>Ongoing</source> + <translation>進行ä¸</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="59"/> + <source>%d days ago</source> + <translation>%d 天å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="60"/> + <source>%d hours ago</source> + <translation>%d å°æ™‚å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="62"/> + <source>%d minutes ago</source> + <translation>%d 分é˜å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="63"/> + <source>one day ago</source> + <translation>1 天å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="64"/> + <source>one hour ago</source> + <translation>1 å°æ™‚å‰</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="65"/> + <source>just now</source> + <translation>ç¾åœ¨</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="66"/> + <source>Failure</source> + <translation>失敗</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="69"/> + <source>Delete</source> + <translation>刪除</translation> + </message> + <message> + <location filename="../src/libclient/chatview.cpp" line="70"/> + <source>Retry</source> + <translation>é‡è©¦</translation> + </message> +</context> +<context> + <name>lrc::ContactModelPimpl</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="474"/> + <source>Searching…</source> + <translation>æ£åœ¨æœå°‹â€¦â€¦</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1009"/> + <source>Invalid ID</source> + <translation>無效 ID</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1012"/> + <source>Username not found</source> + <translation>找ä¸åˆ°ä½¿ç”¨è€…å稱</translation> + </message> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="1015"/> + <source>Couldn't lookup…</source> + <translation>無法查詢……</translation> + </message> +</context> +<context> + <name>lrc::api::ContactModel</name> + <message> + <location filename="../src/libclient/contactmodel.cpp" line="435"/> + <source>Bad URI scheme</source> + <translation>錯誤的 URI çµæ§‹</translation> + </message> +</context> +</TS> \ No newline at end of file