From 9017acdb393f955b50f8f6204426ebb0ad67bed2 Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Sun, 24 Jun 2018 19:17:56 +0200 Subject: [PATCH 001/109] Fix #328: Validate Date header in HTTP Signatures --- api/funkwhale_api/federation/factories.py | 3 ++- api/funkwhale_api/federation/signing.py | 31 +++++++++++++++++++++++ api/tests/federation/test_signing.py | 27 +++++++++++++++++--- changes/changelog.d/328.bugfix | 1 + 4 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 changes/changelog.d/328.bugfix diff --git a/api/funkwhale_api/federation/factories.py b/api/funkwhale_api/federation/factories.py index 7370ebd77..7dad1daa9 100644 --- a/api/funkwhale_api/federation/factories.py +++ b/api/funkwhale_api/federation/factories.py @@ -5,6 +5,7 @@ import requests import requests_http_signature from django.conf import settings from django.utils import timezone +from django.utils.http import http_date from funkwhale_api.factories import registry @@ -39,7 +40,7 @@ class SignedRequestFactory(factory.Factory): default_headers = { "User-Agent": "Test", "Host": "test.host", - "Date": "Right now", + "Date": http_date(timezone.now().timestamp()), "Content-Type": "application/activity+json", } if extracted: diff --git a/api/funkwhale_api/federation/signing.py b/api/funkwhale_api/federation/signing.py index 15525b3e5..5b74b8577 100644 --- a/api/funkwhale_api/federation/signing.py +++ b/api/funkwhale_api/federation/signing.py @@ -1,4 +1,10 @@ +import datetime import logging +import pytz + +from django import forms +from django.utils import timezone +from django.utils.http import parse_http_date import requests import requests_http_signature @@ -7,8 +13,33 @@ from . import exceptions, utils logger = logging.getLogger(__name__) +#  the request Date should be between now - 30s and now + 30s +DATE_HEADER_VALID_FOR = 30 + + +def verify_date(raw_date): + if not raw_date: + raise forms.ValidationError("Missing date header") + + try: + ts = parse_http_date(raw_date) + except ValueError as e: + raise forms.ValidationError(str(e)) + dt = datetime.datetime.utcfromtimestamp(ts) + dt = dt.replace(tzinfo=pytz.utc) + delta = datetime.timedelta(seconds=DATE_HEADER_VALID_FOR) + now = timezone.now() + if dt < now - delta or dt > now + delta: + raise forms.ValidationError( + "Request Date is too far in the future or in the past" + ) + + return dt + def verify(request, public_key): + verify_date(request.headers.get("Date")) + return requests_http_signature.HTTPSignatureAuth.verify( request, key_resolver=lambda **kwargs: public_key, use_auth_header=False ) diff --git a/api/tests/federation/test_signing.py b/api/tests/federation/test_signing.py index 159f31cd9..298462142 100644 --- a/api/tests/federation/test_signing.py +++ b/api/tests/federation/test_signing.py @@ -1,4 +1,7 @@ import cryptography.exceptions +import datetime +from django.utils.http import http_date +from django import forms import pytest from funkwhale_api.federation import keys, signing @@ -36,6 +39,20 @@ def test_verify_fails_with_wrong_key(nodb_factories): signing.verify(prepared_request, wrong_public) +def test_verify_fails_with_wrong_date(nodb_factories, now): + too_old = now - datetime.timedelta(seconds=31) + too_old = http_date(too_old.timestamp()) + private, public = nodb_factories["federation.KeyPair"]() + auth = nodb_factories["federation.SignatureAuth"](key=private) + request = nodb_factories["federation.SignedRequest"]( + auth=auth, headers={"Date": too_old} + ) + prepared_request = request.prepare() + + with pytest.raises(forms.ValidationError): + signing.verify(prepared_request, public) + + def test_can_verify_django_request(factories, fake_request): private_key, public_key = keys.get_key_pair() signed_request = factories["federation.SignedRequest"]( @@ -95,14 +112,18 @@ def test_can_verify_django_request_digest_failure(factories, fake_request): signing.verify_django(django_request, public_key) -def test_can_verify_django_request_failure(factories, fake_request): +def test_can_verify_django_request_failure(factories, fake_request, now): private_key, public_key = keys.get_key_pair() signed_request = factories["federation.SignedRequest"]( auth__key=private_key, auth__headers=["date"] ) prepared = signed_request.prepare() django_request = fake_request.get( - "/", **{"HTTP_DATE": "Wrong", "HTTP_SIGNATURE": prepared.headers["signature"]} + "/", + **{ + "HTTP_DATE": http_date((now + datetime.timedelta(seconds=31)).timestamp()), + "HTTP_SIGNATURE": prepared.headers["signature"], + } ) - with pytest.raises(cryptography.exceptions.InvalidSignature): + with pytest.raises(forms.ValidationError): signing.verify_django(django_request, public_key) diff --git a/changes/changelog.d/328.bugfix b/changes/changelog.d/328.bugfix new file mode 100644 index 000000000..cb28e4c97 --- /dev/null +++ b/changes/changelog.d/328.bugfix @@ -0,0 +1 @@ +Validate Date header in HTTP Signatures (#328) From 39461b8fab17c884030ef61c2e4d4dc09034ff9c Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Sun, 24 Jun 2018 23:42:38 +0200 Subject: [PATCH 002/109] Fix #256: Added troubleshotting and technical overview documentation --- .gitlab-ci.yml | 9 +- CONTRIBUTING | 4 +- changes/changelog.d/256.doc | 1 + docs/Dockerfile | 3 +- docs/architecture.rst | 118 ++++++++++++++++++++ docs/conf.py | 49 ++++----- docs/configuration.rst | 10 ++ docs/index.rst | 2 + docs/troubleshooting.rst | 212 ++++++++++++++++++++++++++++++++++++ docs/upgrading.rst | 2 +- 10 files changed, 379 insertions(+), 31 deletions(-) create mode 100644 changes/changelog.d/256.doc create mode 100644 docs/architecture.rst create mode 100644 docs/troubleshooting.rst diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 684e3233a..ff6da8edf 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -63,12 +63,15 @@ review_docs: BUILD_PATH: "../public" before_script: - cd docs + - apt-get update + - apt-get install -y graphviz + - pip install sphinx + cache: key: "$CI_PROJECT_ID__sphinx" paths: - "$PIP_CACHE_DIR" script: - - pip install sphinx - ./build_docs.sh - mkdir -p /static/docs/$CI_BUILD_REF_SLUG - cp -r $CI_PROJECT_DIR/public/* /static/docs/$CI_BUILD_REF_SLUG @@ -205,8 +208,10 @@ pages: BUILD_PATH: "../public" before_script: - cd docs - script: + - apt-get update + - apt-get install -y graphviz - pip install sphinx + script: - ./build_docs.sh cache: key: "$CI_PROJECT_ID__sphinx" diff --git a/CONTRIBUTING b/CONTRIBUTING index 6fb76a56c..a14a124c3 100644 --- a/CONTRIBUTING +++ b/CONTRIBUTING @@ -1,5 +1,5 @@ Contribute to Funkwhale development -================================== +=================================== First of all, thank you for your interest in the project! We really appreciate the fact that you're about to take some time to read this @@ -111,7 +111,7 @@ Create it like this:: Create docker network -^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^ Create the federation network:: diff --git a/changes/changelog.d/256.doc b/changes/changelog.d/256.doc new file mode 100644 index 000000000..34608e4c3 --- /dev/null +++ b/changes/changelog.d/256.doc @@ -0,0 +1 @@ +Added troubleshotting and technical overview documentation (#256) diff --git a/docs/Dockerfile b/docs/Dockerfile index 1067eb8be..76147bb6d 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -1,4 +1,5 @@ -FROM python:3.6-alpine +FROM python:3.6 +RUN apt-get update && apt-get install -y graphviz RUN pip install sphinx livereload WORKDIR /app/docs diff --git a/docs/architecture.rst b/docs/architecture.rst new file mode 100644 index 000000000..ef52b3b38 --- /dev/null +++ b/docs/architecture.rst @@ -0,0 +1,118 @@ +Architecture +============ + +Funkwhale is made of several components, each of them fulfilling a specific mission: + +.. graphviz:: + + digraph { + node [shape=record]; + rankdir=TB + concentrate=true + user [group="frontend" label="User" fontsize="9"] + webui [group="frontend" label="Web interface (VueJS SPA)" fontsize="9"] + subapps [group="frontend" label="Subsonic-compatible apps (DSub, Clementine)" fontsize="9"] + proxy [label="Reverse proxy (Nginx/Apache)" fontsize="9"] + api [label="API Server (Django)" fontsize="9"] + db [label="Database (PostgreSQL)" fontsize="9"] + cache [label="Cache and message queue (Redis)" fontsize="9"] + worker [label="Worker (Celery)" fontsize="9"] + scheduler [label="Task scheduler (Celery Beat)" fontsize="9"] + + user -> subapps -> proxy + user -> webui -> proxy + cache -> worker + proxy -> api + api -> cache + api -> db + scheduler -> cache + worker -> cache + worker -> db + } + +This graph may looks a bit scary, so we'll detail the role of each component below. + +The user +-------- + +Funkwhale users can interact with your instance using: + +- The official web interface +- Third-party apps + +The web interface +----------------- + +This refers to Funkwhale's built-in web interface, which is a Single Page application +written in Vue JS. This application will interact with Funkwhale's API to retrieve +or persist data. + +Third-party apps +---------------- + +Since Funkwhale implements a subset of the Subsonic API, it's compatible with existing apps such +as DSub, Ultrasonic or Clementine that support this API. Those apps can be used as a replacement +or in conjunction of the web interface, but the underlying data is the same. + +The reverse proxy +----------------- + +Funkwhale's API server should never be exposed directly to the internet, as we require +a reverse proxy (Apache or Nginx) for performance and security reasons. The reverse proxy +will receive client HTTP requests, and: + +- Proxy them to the API server +- Serve requested static files (Audio files, stylesheets, javascript, fonts...) + +The API server +-------------- + +Funkwhale's API server is the central piece of the project. This component is responsible +for answering and processing user requests, manipulate data from the database, send long-running +tasks to workers, etc. + +It's a Python/Django application. + +The database +------------ + +Most of the data such as user accounts, favorites, music metadata or playlist is stored +in a PostgreSQL database. + +The cache/message queue +----------------------- + +Fetching data from the database is sometimes slow or resource hungry. To reduce +the load, Redis act as a cache for data that is considerably faster than a database. + +It is also a message queue that will deliver tasks to the worker. + +The worker +---------- + +Some operations are too long to live in the HTTP request/response cycle. Typically, +importing a bunch of uploaded tracks could take a minute or two. + +To keep the API response time as fast as possible, we offload long-running tasks +to a background process, also known as the Celery worker. + +Typical tasks include: + +- Handling music imports +- Handling federation/ActivityPub messages +- Scanning other instances libraries + +This worker is also able to retry failed tasks, or spawn automatically +more process when the number of received tasks increase. + +The scheduler +------------- + +Some long-running tasks are not triggered by user or external input, but on a recurring +basis instead. The scheduler is responsible for triggering those tasks and put the corresponding +messages in the message queue so the worker can process them. + +Recurring tasks include: + +- Cache cleaning +- Music metadata refreshing diff --git a/docs/conf.py b/docs/conf.py index 01da9bc05..8b1a3d41a 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -20,7 +20,7 @@ import os import sys -sys.path.insert(0, os.path.abspath('../api')) +sys.path.insert(0, os.path.abspath("../api")) import funkwhale_api # NOQA @@ -33,24 +33,24 @@ import funkwhale_api # NOQA # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = [] +extensions = ["sphinx.ext.graphviz"] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] -source_suffix = '.rst' +source_suffix = ".rst" # The master toctree document. -master_doc = 'index' +master_doc = "index" # General information about the project. -project = 'funkwhale' -copyright = '2017, Eliot Berriot' -author = 'Eliot Berriot' +project = "funkwhale" +copyright = "2017, Eliot Berriot" +author = "Eliot Berriot" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -71,10 +71,10 @@ language = None # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This patterns also effect to html_static_path and html_extra_path -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = False @@ -85,7 +85,7 @@ todo_include_todos = False # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'alabaster' +html_theme = "alabaster" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the @@ -96,13 +96,13 @@ html_theme = 'alabaster' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # -- Options for HTMLHelp output ------------------------------------------ # Output file base name for HTML help builder. -htmlhelp_basename = 'funkwhaledoc' +htmlhelp_basename = "funkwhaledoc" # -- Options for LaTeX output --------------------------------------------- @@ -111,15 +111,12 @@ latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # # 'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). # # 'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. # # 'preamble': '', - # Latex figure (float) alignment # # 'figure_align': 'htbp', @@ -129,8 +126,7 @@ latex_elements = { # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'funkwhale.tex', 'funkwhale Documentation', - 'Eliot Berriot', 'manual'), + (master_doc, "funkwhale.tex", "funkwhale Documentation", "Eliot Berriot", "manual") ] @@ -138,10 +134,7 @@ latex_documents = [ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'funkwhale', 'funkwhale Documentation', - [author], 1) -] +man_pages = [(master_doc, "funkwhale", "funkwhale Documentation", [author], 1)] # -- Options for Texinfo output ------------------------------------------- @@ -150,7 +143,13 @@ man_pages = [ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'funkwhale', 'funkwhale Documentation', - author, 'funkwhale', 'One line description of project.', - 'Miscellaneous'), + ( + master_doc, + "funkwhale", + "funkwhale Documentation", + author, + "funkwhale", + "One line description of project.", + "Miscellaneous", + ) ] diff --git a/docs/configuration.rst b/docs/configuration.rst index 7b7751fc6..6ec138e4c 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -124,6 +124,16 @@ On non-docker setup, you don't need to configure this setting. .. note:: This path should not include any trailing slash +.. _setting-REVERSE_PROXY_TYPE: + +``REVERSE_PROXY_TYPE`` +^^^^^^^^^^^^^^^^^^^^^^ + +Default: ``nginx`` + +The type of reverse-proxy behind which Funkwhale is served. Either ``apache2`` +or ``nginx``. This is only used if you are using in-place import. + User permissions ---------------- diff --git a/docs/index.rst b/docs/index.rst index f177a4240..7d200da54 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -13,9 +13,11 @@ Funkwhale is a self-hosted, modern free and open-source music server, heavily in users/index features + architecture installation/index upgrading configuration + troubleshooting importing-music federation api diff --git a/docs/troubleshooting.rst b/docs/troubleshooting.rst new file mode 100644 index 000000000..61fa4c68a --- /dev/null +++ b/docs/troubleshooting.rst @@ -0,0 +1,212 @@ +Troubleshooting +=============== + +Various errors and issues can arise on your Funkwhale instance, caused by configuration errors, +deployment/environment specific issues, or bugs in the software itself. + +On this document, you'll find: + +- Tools and commands you can use to better understand the issues +- A list of common pitfalls and errors and how to solve them +- A collection of links and advice to get help from the community and report new issues + +Diagnose problems +^^^^^^^^^^^^^^^^^ + +Funkwhale is made of several components, each one being a potential cause for failure. Having an even basic overview +of Funkwhale's technical architecture can help you understand what is going on. You can refer to :doc:`the technical architecture ` for that. + +Problems usually fall into one of those categories: + +- **Frontend**: Funkwhale's interface is not loading, not behaving as expected, music is not playing +- **API**: the interface do not display any data or show errors +- **Import**: uploaded/imported tracks are not imported correctly or at all +- **Federation**: you cannot contact other Funkwhale servers, access their library, play federated tracks +- **Everything else** + +Each category comes with its own set of diagnose tools and/or commands we will detail below. We'll also give you simple +steps for each type of problem. Please try those to see if it fix your issues. If none of those works, please report your issue on our +issue tracker. + +Frontend issues +^^^^^^^^^^^^^^^ + +Diagnostic tools: + +- Javascript and network logs from your browser console (see instructions on how to open it in `Chrome `_ and `Firefox `_ +- Proxy and API access and error logs (see :ref:`access-logs`) +- The same operation works from a different browser + +Common problems +*************** + +The front-end is completely blank +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You are visiting Funkwhale, but you don't see anything. + +- Try from a different browser +- Check network errors in your browser console. If you see responses with 40X or 50X statuses, there is probably an issue with the webserver configuration +- If you don't see anything wrong in the network console, check the Javascript console +- Disable your browser extensions (like adblockers) + +Music is not playing +~~~~~~~~~~~~~~~~~~~~ + +You have some tracks in your queue that don't play, or the queue is jumping from one track to the next until +there is no more track available: + +- Try with other tracks. If it works with some tracks but not other tracks, this may means that the failing tracks are not probably imported + or that your browser does not support a specific audio format +- Check the network and javascript console for potential errors + +Tracks are not appending to the queue +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When clicking on "Play", "Play all albums" or "Play all" buttons, some tracks are not appended to the queue. This is +actually a feature of Funkwhale: those tracks have no file associated with them, so we cannot play them. + +Specific pages are loading forever or blank +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When viewing a given page, the page load never ends (you continue to see the spinner), or nothing seems to appear at all: + +- Ensure your internet connection is up and running +- Ensure your instance is up and running +- Check the network and javascript console for potential errors + + +Backend issues +^^^^^^^^^^^^^^ + +Diagnostic tools: + +- Reverse proxy logs: + - Apache logs should be available at :file:`/var/log/apache/access.log` and :file:`/var/log/apache/error.log` + - Nginx logs should be available at :file:`/var/log/nginx/access.log` and :file:`/var/log/nginx/error.log` +- API logs: + - Docker setup: ``docker-compose logs -f --tail=50 api`` (remove the ``--tail`` flag to get the full logs) + - Non-docker setup: ``journalctl -xn -u funkwhale-server`` + +.. note:: + + If you edit your .env file to test a new configuration, you have to restart your services to pick up the changes: + + - Docker setup: ``docker-compose up -d`` + - Non-docker setup: ``systemctl restart funkwhale.target`` + +Common problems +*************** + +Instance work properly, but audio files are not served (404 error) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- If you're using docker, ensure the ``MEDIA_ROOT`` variable is commented in your env file +- Ensure the ``_protected/media`` block points toward the path where media files are stored (``/srv/funkwhale/data/media``, by default) +- If you're using in-place import, ensure :ref:`setting-MUSIC_DIRECTORY_PATH`, :ref:`setting-MUSIC_DIRECTORY_SERVE_PATH` and :ref:`setting-REVERSE_PROXY_TYPE` are configured properly, and that the files are readable by the webserver + +Weakref error when running ``python manage.py `` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +On Python <3.6, you may see this kind of errors when running commands like ``python manage.py migrate``:: + + Exception ignored in: .remove at 0x107e7a6a8> + Traceback (most recent call last): + File "/srv/funkwhale/venv/lib/python3.5/weakref.py", line 117, in remove + TypeError: 'NoneType' object is not callable + +This is caused by a bug in Python (cf https://github.com/celery/celery/issues/3818), and is not affecting in any way +the command you execute. You can safely ignore this error. + +``Your models have changes that are not yet reflected in a migration`` warning +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When running ``python manage.py migrate`` (both in docker or non-docker), you may end-up with this:: + + Operations to perform: + Apply all migrations: account, admin, auth, authtoken, common, contenttypes, dynamic_preferences, favorites, federation, history, music, playlists, radios, requests, sessions, sites, socialaccount, taggit, users + Running migrations: + No migrations to apply. + + Your models have changes that are not yet reflected in a migration, and so won't be applied. + Run 'manage.py makemigrations' to make new migrations, and then re-run 'manage.py migrate' to apply them. + +This warning can be safely ignored. You should not run the suggested ``manage.py makemigrations`` command. + +File import issues +^^^^^^^^^^^^^^^^^^ + +Unless you are using the CLI to import files, imports are send as tasks in a queue to a celery worker that will process them. + +Diagnostic tools: + +- Celery worker logs: + - Docker setup: ``docker-compose logs -f --tail=50 celeryworker`` (remove the ``--tail`` flag to get the full logs) + - Non-docker setup: ``journalctl -xn -u funkwhale-worker`` + +Federation issues +^^^^^^^^^^^^^^^^^ + +Received federations messages are sent to a dedicated task queue and processed asynchronously by a celery worker. + +Diagnostic tools: + +- API logs: + - Docker setup: ``docker-compose logs -f --tail=50 api`` (remove the ``--tail`` flag to get the full logs) + - Non-docker setup: ``journalctl -xn -u funkwhale-server`` +- Celery worker logs: + - Docker setup: ``docker-compose logs -f --tail=50 celeryworker`` (remove the ``--tail`` flag to get the full logs) + - Non-docker setup: ``journalctl -xn -u funkwhale-worker`` + +Common problems +*************** + +I have no access to another instance library +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Check if it works with the demo library (library@demo.funkwhale.audio) +- Check if the remote library received your follow request and approved it +- Trigger a scan via the interface +- Have a look in the celery logs for potential errors during the scan + +Other problems +^^^^^^^^^^^^^^ + +It's a bit hard to give targeted advice about problems that do not fit in the previous categories. However, we can recommend to: + +- Try to identify the scope of the issue and reproduce it reliably +- Ensure your instance is configured as detailed in the installation documentation, and if you did not use the default + values, to check what you changed +- To read the .env file carefuly, as most of the options are described in the comments + + +Report an issue or get help +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Well be more than happy to help you to debug installation and configuration issues. The main channel +for receiving support about your Funkwhale installation is the `#funkwhale-troubleshooting:matrix.org `_ Matrix channel. + +Before asking for help, we'd really appreciate if you took the time to go through this document and try to diagnose the problem yourself. But if you don't find +anything relevant or don't have the time, we'll be there for you! + +Here are a few recommendations on how to structure and what to include in your help requests: + +- Give us as much context as possible about your installation (OS, version, Docker/non-docker, reverse-proxy type, relevant logs and errors, etc.) +- Including screenshots or small gifs or videos can help us considerably when debugging front-end issues + +You can also open issues on our `issue tracker `_. Please have a quick look for +similar issues before doing that, and use the issue tracker only to report bugs, suggest enhancements (both in the software and the documentation) or new features. + +.. warning:: + + If you ever need to share screenshots or urls with someone else, ensure those do not include your personnal token. + This token is binded to your account and can be used to connect and use your account. + + Urls that includes your token looks like: ``https://your.instance/api/v1/trackfiles/42/serve/?jwt=yoursecrettoken`` + +Improving this documentation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you feel like something should be improved in this document (and in the documentation in general), feel free to `edit +it `_ and open a Merge Request. If you lack time or skills +to do that, you can open an issue to discuss that, and someone else will do it. diff --git a/docs/upgrading.rst b/docs/upgrading.rst index 85a2b5057..437613b43 100644 --- a/docs/upgrading.rst +++ b/docs/upgrading.rst @@ -72,7 +72,7 @@ Upgrading the API ^^^^^^^^^^^^^^^^^ On non-docker, upgrade involves a few more commands. We assume your setup -match what is described in :doc:`debian`: +match what is described in :doc:`/installation/debian`: .. parsed-literal:: From f3062f5fbcb40f0df8c01118b59f68718443bccd Mon Sep 17 00:00:00 2001 From: Reg Date: Mon, 25 Jun 2018 21:48:28 +0000 Subject: [PATCH 003/109] Typos --- CONTRIBUTING | 2 +- changes/changelog.d/typos.doc | 1 + deploy/apache.conf | 2 +- deploy/nginx.conf | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 changes/changelog.d/typos.doc diff --git a/CONTRIBUTING b/CONTRIBUTING index 6fb76a56c..9fbda1537 100644 --- a/CONTRIBUTING +++ b/CONTRIBUTING @@ -82,7 +82,7 @@ Visit https://code.eliotberriot.com/funkwhale/funkwhale and clone the repository A note about branches ^^^^^^^^^^^^^^^^^^^^^ -Next release development occurs on the "develop" branch, and releases are made on the "master" branch. Therefor, when submitting Merge Requests, ensure you are merging on the develop branch. +Next release development occurs on the "develop" branch, and releases are made on the "master" branch. Therefore, when submitting Merge Requests, ensure you are merging on the develop branch. Working with docker diff --git a/changes/changelog.d/typos.doc b/changes/changelog.d/typos.doc new file mode 100644 index 000000000..51cc5e8c4 --- /dev/null +++ b/changes/changelog.d/typos.doc @@ -0,0 +1 @@ +Fixed a couple of typos diff --git a/deploy/apache.conf b/deploy/apache.conf index 5f86db7bd..b74e04b33 100644 --- a/deploy/apache.conf +++ b/deploy/apache.conf @@ -34,7 +34,7 @@ Define MUSIC_DIRECTORY_PATH /srv/funkwhale/data/music # TLS # Feel free to use your own configuration for SSL here or simply remove the # lines and move the configuration to the previous server block if you - # don't want to run funkwhale behind https (this is not recommanded) + # don't want to run funkwhale behind https (this is not recommended) # have a look here for let's encrypt configuration: # https://certbot.eff.org/lets-encrypt/debianstretch-apache.html SSLEngine on diff --git a/deploy/nginx.conf b/deploy/nginx.conf index c8f64cc38..2d8412edb 100644 --- a/deploy/nginx.conf +++ b/deploy/nginx.conf @@ -31,7 +31,7 @@ server { # TLS # Feel free to use your own configuration for SSL here or simply remove the # lines and move the configuration to the previous server block if you - # don't want to run funkwhale behind https (this is not recommanded) + # don't want to run funkwhale behind https (this is not recommended) # have a look here for let's encrypt configuration: # https://certbot.eff.org/all-instructions/#debian-9-stretch-nginx ssl_protocols TLSv1.2; From 281bef48bf44aa38b7e94f28433b4b8968b4ccb8 Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Thu, 28 Jun 2018 16:47:45 +0200 Subject: [PATCH 004/109] Fix #339: Subsonic API login is now case insensitive --- api/funkwhale_api/subsonic/authentication.py | 2 +- api/tests/subsonic/test_authentication.py | 12 ++++++++++++ changes/changelog.d/339.bugfix | 1 + 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 changes/changelog.d/339.bugfix diff --git a/api/funkwhale_api/subsonic/authentication.py b/api/funkwhale_api/subsonic/authentication.py index a573a1092..d6edb90cd 100644 --- a/api/funkwhale_api/subsonic/authentication.py +++ b/api/funkwhale_api/subsonic/authentication.py @@ -19,7 +19,7 @@ def authenticate(username, password): password = password.replace("enc:", "", 1) password = binascii.unhexlify(password).decode("utf-8") user = User.objects.get( - username=username, is_active=True, subsonic_api_token=password + username__iexact=username, is_active=True, subsonic_api_token=password ) except (User.DoesNotExist, binascii.Error): raise exceptions.AuthenticationFailed("Wrong username or password.") diff --git a/api/tests/subsonic/test_authentication.py b/api/tests/subsonic/test_authentication.py index b2d2c0400..b0c6b1b32 100644 --- a/api/tests/subsonic/test_authentication.py +++ b/api/tests/subsonic/test_authentication.py @@ -63,3 +63,15 @@ def test_auth_with_inactive_users(api_request, factories): authenticator = authentication.SubsonicAuthentication() with pytest.raises(exceptions.AuthenticationFailed): authenticator.authenticate(request) + + +def test_auth_case_insensitive(api_request, factories): + user = factories["users.User"](username="Hello") + user.subsonic_api_token = "password" + user.save() + request = api_request.get("/", {"u": "hello", "p": "password"}) + + authenticator = authentication.SubsonicAuthentication() + u, _ = authenticator.authenticate(request) + + assert user == u diff --git a/changes/changelog.d/339.bugfix b/changes/changelog.d/339.bugfix new file mode 100644 index 000000000..3f4d82ea4 --- /dev/null +++ b/changes/changelog.d/339.bugfix @@ -0,0 +1 @@ +Subsonic API login is now case insensitive (#339) From cac543c9ba84680c7e09d3cadd921c923e9fbe82 Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Thu, 28 Jun 2018 16:51:29 +0200 Subject: [PATCH 005/109] Fix #332: Ensure 750 permissions on CI artifacts --- .gitlab-ci.yml | 5 ++++- changes/changelog.d/332.bugfix | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 changes/changelog.d/332.bugfix diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ff6da8edf..3165213e2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -184,6 +184,7 @@ build_front: # this is to ensure we don't have any errors in the output, # cf https://code.eliotberriot.com/funkwhale/funkwhale/issues/169 - yarn run build | tee /dev/stderr | (! grep -i 'ERROR in') + - chmod -R 750 front/dist cache: key: "$CI_PROJECT_ID__front_dependencies" paths: @@ -248,7 +249,9 @@ build_api: name: "api_${CI_COMMIT_REF_NAME}" paths: - api - script: echo Done! + script: + - chmod -R 750 api + - echo Done! only: - tags@funkwhale/funkwhale - master@funkwhale/funkwhale diff --git a/changes/changelog.d/332.bugfix b/changes/changelog.d/332.bugfix new file mode 100644 index 000000000..a5d13f01e --- /dev/null +++ b/changes/changelog.d/332.bugfix @@ -0,0 +1 @@ +Ensure 750 permissions on CI artifacts (#332) From a0a75c99198b3b942ead8f545d31caddd7025b68 Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Sat, 30 Jun 2018 11:11:45 +0200 Subject: [PATCH 006/109] See #161: initial setup to collect/compile messages with vue-gettext --- front/package.json | 6 +- front/scripts/i18n-compile.sh | 3 + front/scripts/i18n-extract.sh | 25 +++ front/src/locales.js | 13 ++ front/src/main.js | 24 +++ front/src/translations.json | 1 + front/yarn.lock | 319 +++++++++++++++++++++++++++++++++- 7 files changed, 381 insertions(+), 10 deletions(-) create mode 100755 front/scripts/i18n-compile.sh create mode 100755 front/scripts/i18n-extract.sh create mode 100644 front/src/locales.js create mode 100644 front/src/translations.json diff --git a/front/package.json b/front/package.json index 3dec9c257..8ffbcf729 100644 --- a/front/package.json +++ b/front/package.json @@ -8,8 +8,8 @@ "dev": "node build/dev-server.js", "start": "node build/dev-server.js", "build": "node build/build.js", - "i18n-extract": "find src/ -name '*.vue' | xargs vendor/vue-i18n-xgettext/index.js > ../po/en.po", - "i18n-compile": "node build/i18n.js", + "i18n-extract": "scripts/i18n-extract.sh", + "i18n-compile": "scripts/i18n-compile.sh", "unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run", "unit-watch": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js", "e2e": "node test/e2e/runner.js", @@ -34,6 +34,7 @@ "semantic-ui-css": "^2.2.10", "showdown": "^1.8.6", "vue": "^2.5.16", + "vue-gettext": "^2.0.31", "vue-lazyload": "^1.1.4", "vue-masonry": "^0.10.16", "vue-router": "^2.3.1", @@ -61,6 +62,7 @@ "cross-env": "^4.0.0", "cross-spawn": "^5.0.1", "css-loader": "^0.28.0", + "easygettext": "^2.5.0", "es6-promise": "^4.2.2", "eslint": "^3.19.0", "eslint-config-standard": "^6.2.1", diff --git a/front/scripts/i18n-compile.sh b/front/scripts/i18n-compile.sh new file mode 100755 index 000000000..211f8ee8c --- /dev/null +++ b/front/scripts/i18n-compile.sh @@ -0,0 +1,3 @@ +#!/bin/bash -eux +locales=$(tail -n +2 src/locales.js | sed -e 's/export default //' | jq '.locales[].code' | xargs echo) +find locales -name '*.po' | xargs $(yarn bin gettext-extract)/gettext-compile --output src/translations.json diff --git a/front/scripts/i18n-extract.sh b/front/scripts/i18n-extract.sh new file mode 100755 index 000000000..e8994f866 --- /dev/null +++ b/front/scripts/i18n-extract.sh @@ -0,0 +1,25 @@ +#!/bin/bash -eux +locales=$(tail -n +2 src/locales.js | sed -e 's/export default //' | jq '.locales[].code' | xargs echo) +locales_dir="locales" +sources=$(find src -name '*.vue' -o -name '*.html' 2> /dev/null) +js_sources=$(find src -name '*.vue' -o -name '*.js') +touch $locales_dir/app.pot + +# Create a main .pot template, then generate .po files for each available language. +# Extract gettext strings from templates files and create a POT dictionary template. +$(yarn bin gettext-extract)/gettext-extract --attribute v-translate --quiet --output $locales_dir/app.pot $sources +xgettext --language=JavaScript --keyword=npgettext:1c,2,3 \ + --from-code=utf-8 --join-existing --no-wrap \ + --package-name=$(node -e "console.log(require('./package.json').name);") \ + --package-version=$(node -e "console.log(require('./package.json').version);") \ + --output $locales_dir/app.pot $js_sources + +# Generate .po files for each available language. +echo $locales +for lang in $locales; do \ + po_file=$locales_dir/$lang/LC_MESSAGES/app.po; \ + echo "msgmerge --update $po_file "; \ + mkdir -p $(dirname $po_file); \ + [ -f $po_file ] && msgmerge --lang=$lang --update $po_file $locales_dir/app.pot || msginit --no-translator --locale=$lang --input=$locales_dir/app.pot --output-file=$po_file; \ + msgattrib --no-wrap --no-obsolete -o $po_file $po_file; \ +done; diff --git a/front/src/locales.js b/front/src/locales.js new file mode 100644 index 000000000..1253354c5 --- /dev/null +++ b/front/src/locales.js @@ -0,0 +1,13 @@ +/* eslint-disable */ +export default { + "locales": [ + { + "code": "en_US", + "label": "English (United-States)" + }, + { + "code": "fr_FR", + "label": "Français" + } + ] +} diff --git a/front/src/main.js b/front/src/main.js index 181fd66b3..b4522eb23 100644 --- a/front/src/main.js +++ b/front/src/main.js @@ -15,7 +15,11 @@ import i18next from 'i18next' import i18nextFetch from 'i18next-fetch-backend' import VueI18Next from '@panter/vue-i18next' import store from './store' +import GetTextPlugin from 'vue-gettext' import { sync } from 'vuex-router-sync' +import translations from './translations.json' +import locales from '@/locales' + import filters from '@/filters' // eslint-disable-line import globals from '@/components/globals' // eslint-disable-line @@ -29,6 +33,26 @@ window.$ = window.jQuery = require('jquery') require('semantic-ui-css/semantic.js') require('masonry-layout') +Vue.use(GetTextPlugin, { + availableLanguages: (function () { + let l = {} + locales.locales.forEach(c => { + l[c.code] = c.label + }) + return l + })(), + defaultLanguage: 'en_US', + languageVmMixin: { + computed: { + currentKebabCase: function () { + return this.current.toLowerCase().replace('_', '-') + } + } + }, + translations: translations, + silent: true +}) + Vue.use(VueI18Next) Vue.use(VueMasonryPlugin) Vue.use(VueLazyload) diff --git a/front/src/translations.json b/front/src/translations.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/front/src/translations.json @@ -0,0 +1 @@ +{} diff --git a/front/yarn.lock b/front/yarn.lock index 7cf3cb116..42dfdc533 100644 --- a/front/yarn.lock +++ b/front/yarn.lock @@ -8,6 +8,34 @@ dependencies: deepmerge "^2.0.0" +"@types/babel-types@*", "@types/babel-types@^7.0.0": + version "7.0.4" + resolved "https://registry.yarnpkg.com/@types/babel-types/-/babel-types-7.0.4.tgz#bfd5b0d0d1ba13e351dff65b6e52783b816826c8" + +"@types/babylon@^6.16.2": + version "6.16.3" + resolved "https://registry.yarnpkg.com/@types/babylon/-/babylon-6.16.3.tgz#c2937813a89fcb5e79a00062fc4a8b143e7237bb" + dependencies: + "@types/babel-types" "*" + +"@types/node@*": + version "10.5.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.5.1.tgz#d578446f4abff5c0b49ade9b4e5274f6badaadfc" + +"@vue/component-compiler-utils@^1.2.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@vue/component-compiler-utils/-/component-compiler-utils-1.3.1.tgz#686f0b913d59590ae327b2a1cb4b6d9b931bbe0e" + dependencies: + consolidate "^0.15.1" + hash-sum "^1.0.2" + lru-cache "^4.1.2" + merge-source-map "^1.1.0" + postcss "^6.0.20" + postcss-selector-parser "^3.1.1" + prettier "^1.13.0" + source-map "^0.5.6" + vue-template-es2015-compiler "^1.6.0" + abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" @@ -36,17 +64,23 @@ acorn-dynamic-import@^2.0.0: dependencies: acorn "^4.0.3" +acorn-globals@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-3.1.0.tgz#fd8270f71fbb4996b004fa880ee5d46573a731bf" + dependencies: + acorn "^4.0.4" + acorn-jsx@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" dependencies: acorn "^3.0.4" -acorn@^3.0.4: +acorn@^3.0.4, acorn@^3.1.0: version "3.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" -acorn@^4.0.3: +acorn@^4.0.3, acorn@^4.0.4, acorn@~4.0.2: version "4.0.13" resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" @@ -54,6 +88,10 @@ acorn@^5.0.0, acorn@^5.3.0, acorn@^5.5.0: version "5.5.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.5.3.tgz#f473dd47e0277a08e28e9bec5aeeb04751f0b8c9" +acorn@^5.5.3: + version "5.7.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.1.tgz#f095829297706a7c9776958c0afc8930a9b9d9d8" + after@0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" @@ -227,6 +265,10 @@ arrify@^1.0.0, arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" +asap@~2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + asn1.js@^4.0.0: version "4.10.1" resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" @@ -1307,6 +1349,20 @@ chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +character-parser@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/character-parser/-/character-parser-2.2.0.tgz#c7ce28f36d4bcd9744e5ffc2c5fcde1c73261fc0" + dependencies: + is-regex "^1.0.3" + check-types@^7.3.0: version "7.3.0" resolved "https://registry.yarnpkg.com/check-types/-/check-types-7.3.0.tgz#468f571a4435c24248f5fd0cb0e8d87c3c341e7d" @@ -1332,6 +1388,17 @@ cheerio@^0.22.0: lodash.reject "^4.4.0" lodash.some "^4.4.0" +cheerio@^1.0.0-rc.2: + version "1.0.0-rc.2" + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.2.tgz#4b9f53a81b27e4d5dac31c0ffd0cfa03cc6830db" + dependencies: + css-select "~1.2.0" + dom-serializer "~0.1.0" + entities "~1.1.1" + htmlparser2 "^3.9.1" + lodash "^4.15.0" + parse5 "^3.0.1" + chokidar@^1.4.1: version "1.7.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468" @@ -1405,7 +1472,7 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -clean-css@4.1.x: +clean-css@4.1.x, clean-css@^4.1.11: version "4.1.11" resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.1.11.tgz#2ecdf145aba38f54740f26cefd0ff3e03e125d6a" dependencies: @@ -1632,6 +1699,21 @@ consolidate@^0.14.0: dependencies: bluebird "^3.1.1" +consolidate@^0.15.1: + version "0.15.1" + resolved "https://registry.yarnpkg.com/consolidate/-/consolidate-0.15.1.tgz#21ab043235c71a07d45d9aad98593b0dba56bab7" + dependencies: + bluebird "^3.1.1" + +constantinople@^3.0.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/constantinople/-/constantinople-3.1.2.tgz#d45ed724f57d3d10500017a7d3a889c1381ae647" + dependencies: + "@types/babel-types" "^7.0.0" + "@types/babylon" "^6.16.2" + babel-types "^6.26.0" + babylon "^6.18.0" + constants-browserify@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" @@ -2116,6 +2198,10 @@ doctrine@^2.0.0: dependencies: esutils "^2.0.2" +doctypes@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/doctypes/-/doctypes-1.1.0.tgz#ea80b106a87538774e8a3a4a5afe293de489e0a9" + dom-converter@~0.1: version "0.1.4" resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.1.4.tgz#a45ef5727b890c9bffe6d7c876e7b19cb0e17f3b" @@ -2182,6 +2268,12 @@ domutils@^1.5.1: dom-serializer "0" domelementtype "1" +dot-prop@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" + dependencies: + is-obj "^1.0.0" + duplexer@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" @@ -2195,6 +2287,18 @@ duplexify@^3.4.2, duplexify@^3.5.3: readable-stream "^2.0.0" stream-shift "^1.0.0" +easygettext@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/easygettext/-/easygettext-2.5.0.tgz#56c695816482cb6ab29a3c3454998274d8845972" + dependencies: + "@vue/component-compiler-utils" "^1.2.1" + acorn "^5.5.3" + cheerio "^1.0.0-rc.2" + minimist "^1.2.0" + pofile "^1.0.10" + pug "^2.0.3" + vue-template-compiler "^2.5.16" + ecc-jsbn@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" @@ -3780,6 +3884,13 @@ is-equal-shallow@^0.1.3: dependencies: is-primitive "^2.0.0" +is-expression@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-expression/-/is-expression-3.0.0.tgz#39acaa6be7fd1f3471dc42c7416e61c24317ac9f" + dependencies: + acorn "~4.0.2" + object-assign "^4.0.1" + is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -3866,6 +3977,10 @@ is-number@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" +is-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + is-odd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-2.0.0.tgz#7646624671fd7ea558ccd9a2795182f2958f1b24" @@ -3906,10 +4021,20 @@ is-primitive@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" +is-promise@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + is-property@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" +is-regex@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + dependencies: + has "^1.0.1" + is-resolvable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" @@ -4022,6 +4147,10 @@ js-logger@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/js-logger/-/js-logger-1.4.1.tgz#f0230dc5e84e120f213d6e5a6b767a913d290335" +js-stringify@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db" + js-tokens@^3.0.0, js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" @@ -4105,6 +4234,13 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" +jstransformer@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/jstransformer/-/jstransformer-1.0.0.tgz#ed8bf0921e2f3f1ed4d5c1a44f68709ed24722c3" + dependencies: + is-promise "^2.0.0" + promise "^7.0.1" + jwt-decode@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/jwt-decode/-/jwt-decode-2.2.0.tgz#7d86bd56679f58ce6a84704a657dd392bba81a79" @@ -4503,6 +4639,10 @@ lodash@^4.0.0, lodash@^4.0.1, lodash@^4.14.0, lodash@^4.17.2, lodash@^4.17.3, lo version "4.17.5" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" +lodash@^4.15.0: + version "4.17.10" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" + log-symbols@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" @@ -4554,6 +4694,13 @@ lru-cache@^3.2.0: dependencies: pseudomap "^1.0.1" +lru-cache@^4.1.2: + version "4.1.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c" + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + lru-cache@~2.6.5: version "2.6.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.6.5.tgz#e56d6354148ede8d7707b58d143220fd08df0fd5" @@ -4649,6 +4796,12 @@ merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" +merge-source-map@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646" + dependencies: + source-map "^0.6.1" + methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" @@ -5346,6 +5499,12 @@ parse-json@^2.2.0: dependencies: error-ex "^1.2.0" +parse5@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c" + dependencies: + "@types/node" "*" + parsejson@0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/parsejson/-/parsejson-0.0.3.tgz#ab7e3759f209ece99437973f7d0f1f64ae0e64ab" @@ -5506,6 +5665,10 @@ pluralize@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" +pofile@^1.0.10: + version "1.0.11" + resolved "https://registry.yarnpkg.com/pofile/-/pofile-1.0.11.tgz#35aff58c17491d127a07336d5522ebc9df57c954" + pofile@^1.0.2: version "1.0.10" resolved "https://registry.yarnpkg.com/pofile/-/pofile-1.0.10.tgz#503dda9499403984e83ff4489ba2d80af276172a" @@ -5737,6 +5900,14 @@ postcss-selector-parser@^2.0.0, postcss-selector-parser@^2.2.2: indexes-of "^1.0.1" uniq "^1.0.1" +postcss-selector-parser@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz#4f875f4afb0c96573d5cf4d74011aee250a7e865" + dependencies: + dot-prop "^4.1.1" + indexes-of "^1.0.1" + uniq "^1.0.1" + postcss-svgo@^2.1.1: version "2.1.6" resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-2.1.6.tgz#b6df18aa613b666e133f08adb5219c2684ac108d" @@ -5783,6 +5954,14 @@ postcss@^6.0.1: source-map "^0.6.1" supports-color "^5.3.0" +postcss@^6.0.20: + version "6.0.23" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.23.tgz#61c82cc328ac60e677645f979054eb98bc0e3324" + dependencies: + chalk "^2.4.1" + source-map "^0.6.1" + supports-color "^5.4.0" + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -5795,6 +5974,10 @@ preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" +prettier@^1.13.0: + version "1.13.7" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.13.7.tgz#850f3b8af784a49a6ea2d2eaa7ed1428a34b7281" + pretty-error@^2.0.2: version "2.1.1" resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.1.tgz#5f4f87c8f91e5ae3f3ba87ab4cf5e03b1a17f1a3" @@ -5822,6 +6005,12 @@ promise-inflight@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" +promise@^7.0.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" + dependencies: + asap "~2.0.3" + proto-list@~1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" @@ -5864,6 +6053,99 @@ public-encrypt@^4.0.0: parse-asn1 "^5.0.0" randombytes "^2.0.1" +pug-attrs@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/pug-attrs/-/pug-attrs-2.0.3.tgz#a3095f970e64151f7bdad957eef55fb5d7905d15" + dependencies: + constantinople "^3.0.1" + js-stringify "^1.0.1" + pug-runtime "^2.0.4" + +pug-code-gen@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pug-code-gen/-/pug-code-gen-2.0.1.tgz#0951ec83225d74d8cfc476a7f99a259b5f7d050c" + dependencies: + constantinople "^3.0.1" + doctypes "^1.1.0" + js-stringify "^1.0.1" + pug-attrs "^2.0.3" + pug-error "^1.3.2" + pug-runtime "^2.0.4" + void-elements "^2.0.1" + with "^5.0.0" + +pug-error@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/pug-error/-/pug-error-1.3.2.tgz#53ae7d9d29bb03cf564493a026109f54c47f5f26" + +pug-filters@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/pug-filters/-/pug-filters-3.1.0.tgz#27165555bc04c236e4aa2b0366246dfa021b626e" + dependencies: + clean-css "^4.1.11" + constantinople "^3.0.1" + jstransformer "1.0.0" + pug-error "^1.3.2" + pug-walk "^1.1.7" + resolve "^1.1.6" + uglify-js "^2.6.1" + +pug-lexer@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/pug-lexer/-/pug-lexer-4.0.0.tgz#210c18457ef2e1760242740c5e647bd794cec278" + dependencies: + character-parser "^2.1.1" + is-expression "^3.0.0" + pug-error "^1.3.2" + +pug-linker@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/pug-linker/-/pug-linker-3.0.5.tgz#9e9a7ae4005682d027deeb96b000f88eeb83a02f" + dependencies: + pug-error "^1.3.2" + pug-walk "^1.1.7" + +pug-load@^2.0.11: + version "2.0.11" + resolved "https://registry.yarnpkg.com/pug-load/-/pug-load-2.0.11.tgz#e648e57ed113fe2c1f45d57858ea2bad6bc01527" + dependencies: + object-assign "^4.1.0" + pug-walk "^1.1.7" + +pug-parser@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/pug-parser/-/pug-parser-5.0.0.tgz#e394ad9b3fca93123940aff885c06e44ab7e68e4" + dependencies: + pug-error "^1.3.2" + token-stream "0.0.1" + +pug-runtime@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pug-runtime/-/pug-runtime-2.0.4.tgz#e178e1bda68ab2e8c0acfc9bced2c54fd88ceb58" + +pug-strip-comments@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pug-strip-comments/-/pug-strip-comments-1.0.3.tgz#f1559592206edc6f85310dacf4afb48a025af59f" + dependencies: + pug-error "^1.3.2" + +pug-walk@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/pug-walk/-/pug-walk-1.1.7.tgz#c00d5c5128bac5806bec15d2b7e7cdabe42531f3" + +pug@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/pug/-/pug-2.0.3.tgz#71cba82537c95a5eab7ed04696e4221f53aa878e" + dependencies: + pug-code-gen "^2.0.1" + pug-filters "^3.1.0" + pug-lexer "^4.0.0" + pug-linker "^3.0.5" + pug-load "^2.0.11" + pug-parser "^5.0.0" + pug-runtime "^2.0.4" + pug-strip-comments "^1.0.3" + pump@^2.0.0, pump@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" @@ -6949,6 +7231,12 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" +supports-color@^5.4.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + dependencies: + has-flag "^3.0.0" + svgo@^0.7.0: version "0.7.2" resolved "https://registry.yarnpkg.com/svgo/-/svgo-0.7.2.tgz#9f5772413952135c6fefbf40afe6a4faa88b4bb5" @@ -7090,6 +7378,10 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" +token-stream@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/token-stream/-/token-stream-0.0.1.tgz#ceeefc717a76c4316f126d0b9dbaa55d7e7df01a" + toposort@^1.0.0: version "1.0.6" resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.6.tgz#c31748e55d210effc00fdcdc7d6e68d7d7bb9cec" @@ -7172,7 +7464,7 @@ uglify-js@3.3.x: commander "~2.15.0" source-map "~0.6.1" -uglify-js@^2.6, uglify-js@^2.8.29: +uglify-js@^2.6, uglify-js@^2.6.1, uglify-js@^2.8.29: version "2.8.29" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.29.tgz#29c5733148057bb4e1f75df35b7a9cb72e6a59dd" dependencies: @@ -7357,10 +7649,14 @@ vm-browserify@0.0.4: dependencies: indexof "0.0.1" -void-elements@^2.0.0: +void-elements@^2.0.0, void-elements@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" +vue-gettext@^2.0.31: + version "2.0.31" + resolved "https://registry.yarnpkg.com/vue-gettext/-/vue-gettext-2.0.31.tgz#0f113bea6aed747e2a809ae4a0db83eaac0b07fc" + vue-hot-reload-api@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.0.tgz#97976142405d13d8efae154749e88c4e358cf926" @@ -7416,14 +7712,14 @@ vue-style-loader@^3.0.0, vue-style-loader@^3.0.1: hash-sum "^1.0.2" loader-utils "^1.0.2" -vue-template-compiler@^2.3.3: +vue-template-compiler@^2.3.3, vue-template-compiler@^2.5.16: version "2.5.16" resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.5.16.tgz#93b48570e56c720cdf3f051cc15287c26fbd04cb" dependencies: de-indent "^1.0.2" he "^1.1.0" -vue-template-es2015-compiler@^1.2.2: +vue-template-es2015-compiler@^1.2.2, vue-template-es2015-compiler@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.6.0.tgz#dc42697133302ce3017524356a6c61b7b69b4a18" @@ -7431,7 +7727,7 @@ vue-upload-component@^2.7.4: version "2.8.5" resolved "https://registry.yarnpkg.com/vue-upload-component/-/vue-upload-component-2.8.5.tgz#680de2934f55c6a38da7b382d0f37fd79995dd42" -vue@^2.0.0, vue@^2.3.3: +vue@^2.0.0, vue@^2.5.16: version "2.5.16" resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.16.tgz#07edb75e8412aaeed871ebafa99f4672584a0085" @@ -7575,6 +7871,13 @@ window-size@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d" +with@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/with/-/with-5.1.1.tgz#fa4daa92daf32c4ea94ed453c81f04686b575dfe" + dependencies: + acorn "^3.1.0" + acorn-globals "^3.0.0" + wordwrap@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f" From 6fa64821c80195b584ba7d82adbeda75a6cbbf36 Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Sat, 30 Jun 2018 11:12:46 +0200 Subject: [PATCH 007/109] See #161: ensure we never commit compiled files --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 2582cc534..157871899 100644 --- a/.gitignore +++ b/.gitignore @@ -91,3 +91,5 @@ data/ po/*.po docs/swagger _build +front/src/translations.json +front/locales/*.pot From d932589ac245c38d4eb3e5c892273d0aaf258fe3 Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Sat, 30 Jun 2018 11:34:59 +0200 Subject: [PATCH 008/109] See #161: initial poc/pos on App --- .gitignore | 1 - front/locales/app.pot | 66 ++++++++++++++++++++++++++ front/locales/en_US/LC_MESSAGES/app.po | 66 ++++++++++++++++++++++++++ front/locales/fr_FR/LC_MESSAGES/app.po | 66 ++++++++++++++++++++++++++ front/src/App.vue | 32 ++++++------- 5 files changed, 214 insertions(+), 17 deletions(-) create mode 100644 front/locales/app.pot create mode 100644 front/locales/en_US/LC_MESSAGES/app.po create mode 100644 front/locales/fr_FR/LC_MESSAGES/app.po diff --git a/.gitignore b/.gitignore index 157871899..2b1de550a 100644 --- a/.gitignore +++ b/.gitignore @@ -92,4 +92,3 @@ po/*.po docs/swagger _build front/src/translations.json -front/locales/*.pot diff --git a/front/locales/app.pot b/front/locales/app.pot new file mode 100644 index 000000000..1d6aa5759 --- /dev/null +++ b/front/locales/app.pot @@ -0,0 +1,66 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the front package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: front 1.0.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-06-30 11:34+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: src/App.vue:51 +msgid "About Funkwhale" +msgstr "" + +#: src/App.vue:53 +msgid "Funkwhale is a free and open-source project run by volunteers. You can help us improve the platform by reporting bugs, suggesting features and share the project with your friends!" +msgstr "" + +#: src/App.vue:29 +msgid "Links" +msgstr "" + +#: src/App.vue:38 +msgid "Source code" +msgstr "" + +#: src/App.vue:37 +msgid "Source code (%{version})" +msgstr "" + +#: src/App.vue:56 +msgid "The funkwhale logo was kindly designed and provided by Francis Gading." +msgstr "" + +#: src/App.vue:118 +msgid "This will erase your local data and disconnect you, do you want to continue?" +msgstr "" + +#: src/App.vue:5 +msgid "Choose your instance" +msgstr "" + +#: src/App.vue:7 +msgid "You need to select an instance in order to continue" +msgstr "" + +#: src/App.vue:33 +msgid "About this instance" +msgstr "" + +#: src/App.vue:36 +msgid "Documentation" +msgstr "" + +#: src/App.vue:43 +msgid "Use another instance" +msgstr "" diff --git a/front/locales/en_US/LC_MESSAGES/app.po b/front/locales/en_US/LC_MESSAGES/app.po new file mode 100644 index 000000000..20d2591fa --- /dev/null +++ b/front/locales/en_US/LC_MESSAGES/app.po @@ -0,0 +1,66 @@ +# English translations for front package. +# Copyright (C) 2018 THE front'S COPYRIGHT HOLDER +# This file is distributed under the same license as the front package. +# Automatically generated, 2018. +# +msgid "" +msgstr "" +"Project-Id-Version: front 1.0.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-06-30 11:34+0200\n" +"PO-Revision-Date: 2018-06-30 11:34+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: en_US\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: src/App.vue:51 +msgid "About Funkwhale" +msgstr "About Funkwhale" + +#: src/App.vue:53 +msgid "Funkwhale is a free and open-source project run by volunteers. You can help us improve the platform by reporting bugs, suggesting features and share the project with your friends!" +msgstr "Funkwhale is a free and open-source project run by volunteers. You can help us improve the platform by reporting bugs, suggesting features and share the project with your friends!" + +#: src/App.vue:29 +msgid "Links" +msgstr "Links" + +#: src/App.vue:38 +msgid "Source code" +msgstr "Source code" + +#: src/App.vue:37 +msgid "Source code (%{version})" +msgstr "Source code (%{version})" + +#: src/App.vue:56 +msgid "The funkwhale logo was kindly designed and provided by Francis Gading." +msgstr "The funkwhale logo was kindly designed and provided by Francis Gading." + +#: src/App.vue:118 +msgid "This will erase your local data and disconnect you, do you want to continue?" +msgstr "This will erase your local data and disconnect you, do you want to continue?" + +#: src/App.vue:5 +msgid "Choose your instance" +msgstr "Choose your instance" + +#: src/App.vue:7 +msgid "You need to select an instance in order to continue" +msgstr "You need to select an instance in order to continue" + +#: src/App.vue:33 +msgid "About this instance" +msgstr "About this instance" + +#: src/App.vue:36 +msgid "Documentation" +msgstr "Documentation" + +#: src/App.vue:43 +msgid "Use another instance" +msgstr "Use another instance" diff --git a/front/locales/fr_FR/LC_MESSAGES/app.po b/front/locales/fr_FR/LC_MESSAGES/app.po new file mode 100644 index 000000000..da6b50bfe --- /dev/null +++ b/front/locales/fr_FR/LC_MESSAGES/app.po @@ -0,0 +1,66 @@ +# French translations for front package. +# Copyright (C) 2018 THE front'S COPYRIGHT HOLDER +# This file is distributed under the same license as the front package. +# Automatically generated, 2018. +# +msgid "" +msgstr "" +"Project-Id-Version: front 1.0.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-06-30 11:34+0200\n" +"PO-Revision-Date: 2018-06-30 11:34+0200\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: src/App.vue:51 +msgid "About Funkwhale" +msgstr "" + +#: src/App.vue:53 +msgid "Funkwhale is a free and open-source project run by volunteers. You can help us improve the platform by reporting bugs, suggesting features and share the project with your friends!" +msgstr "" + +#: src/App.vue:29 +msgid "Links" +msgstr "" + +#: src/App.vue:38 +msgid "Source code" +msgstr "" + +#: src/App.vue:37 +msgid "Source code (%{version})" +msgstr "" + +#: src/App.vue:56 +msgid "The funkwhale logo was kindly designed and provided by Francis Gading." +msgstr "" + +#: src/App.vue:118 +msgid "This will erase your local data and disconnect you, do you want to continue?" +msgstr "" + +#: src/App.vue:5 +msgid "Choose your instance" +msgstr "" + +#: src/App.vue:7 +msgid "You need to select an instance in order to continue" +msgstr "" + +#: src/App.vue:33 +msgid "About this instance" +msgstr "" + +#: src/App.vue:36 +msgid "Documentation" +msgstr "" + +#: src/App.vue:43 +msgid "Use another instance" +msgstr "" diff --git a/front/src/App.vue b/front/src/App.vue index 56dbe0aad..0d66cfc9a 100644 --- a/front/src/App.vue +++ b/front/src/App.vue @@ -2,14 +2,14 @@
-

{{ $t('Choose your instance') }}

+

{{ $gettext('Choose your instance') }}

-

{{ $t('You need to select an instance in order to continue') }}

+

{{ $gettext('You need to select an instance in order to continue') }}

- +
-

{{ $t('Suggested choices') }}

+

{{ $gettext('Suggested choices') }}