/** Get the i18n resource strings in the language of the current user */
  @RequestMapping(value = "/i18n", method = GET, produces = APPLICATION_JSON_VALUE)
  @ResponseBody
  public Map<String, String> getI18nStrings() {
    Map<String, String> translations = new HashMap<>();

    ResourceBundle bundle = languageService.getBundle();
    for (String key : bundle.keySet()) {
      translations.put(key, bundle.getString(key));
    }

    return translations;
  }
  @RequestMapping(value = "/{entityName}/{id:.+}", method = POST, params = "_method=GET")
  @ResponseBody
  public Map<String, Object> retrieveEntityPost(
      @PathVariable("entityName") String entityName,
      @PathVariable("id") Object id,
      @RequestParam(value = "attrs", required = false) AttributeFilter attributeFilter) {
    EntityMetaData entityMeta = dataService.getEntityMetaData(entityName);
    Fetch fetch =
        AttributeFilterToFetchConverter.convert(
            attributeFilter, entityMeta, languageService.getCurrentUserLanguageCode());

    Entity entity = dataService.findOne(entityName, id, fetch);
    if (entity == null) {
      throw new UnknownEntityException(entityName + " [" + id + "] not found");
    }

    return createEntityResponse(entity, fetch, true);
  }
  private EntityCollectionResponseV2 createEntityCollectionResponse(
      String entityName, EntityCollectionRequestV2 request, HttpServletRequest httpRequest) {
    EntityMetaData meta = dataService.getEntityMetaData(entityName);

    Query q = request.getQ() != null ? request.getQ().createQuery(meta) : new QueryImpl();
    q.pageSize(request.getNum()).offset(request.getStart()).sort(request.getSort());
    Fetch fetch =
        AttributeFilterToFetchConverter.convert(
            request.getAttrs(), meta, languageService.getCurrentUserLanguageCode());
    if (fetch != null) {
      q.fetch(fetch);
    }

    if (request.getAggs() != null) {
      // return aggregates for aggregate query
      AggregateQuery aggsQ = request.getAggs().createAggregateQuery(meta, q);
      AttributeMetaData xAttr = aggsQ.getAttributeX();
      AttributeMetaData yAttr = aggsQ.getAttributeY();
      if (xAttr == null && yAttr == null) {
        throw new MolgenisQueryException("Aggregate query is missing 'x' or 'y' attribute");
      }
      AggregateResult aggs = dataService.aggregate(entityName, aggsQ);
      AttributeMetaDataResponseV2 xAttrResponse =
          xAttr != null
              ? new AttributeMetaDataResponseV2(
                  entityName, meta, xAttr, fetch, permissionService, dataService, languageService)
              : null;
      AttributeMetaDataResponseV2 yAttrResponse =
          yAttr != null
              ? new AttributeMetaDataResponseV2(
                  entityName, meta, yAttr, fetch, permissionService, dataService, languageService)
              : null;
      return new EntityAggregatesResponse(
          aggs, xAttrResponse, yAttrResponse, BASE_URI + '/' + entityName);
    } else {
      Long count = dataService.count(entityName, q);
      Iterable<Entity> it;
      if (count > 0) {
        it =
            new Iterable<Entity>() {
              @Override
              public Iterator<Entity> iterator() {
                return dataService.findAll(entityName, q).iterator();
              }
            };
      } else {
        it = Collections.emptyList();
      }
      EntityPager pager = new EntityPager(request.getStart(), request.getNum(), count, it);

      List<Map<String, Object>> entities = new ArrayList<>();
      for (Entity entity : it) {
        Map<String, Object> responseData = new LinkedHashMap<String, Object>();
        createEntityValuesResponse(entity, fetch, responseData);
        entities.add(responseData);
      }

      UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(getFullURL(httpRequest));

      String prevHref = null;
      if (pager.getPrevStart() != null) {
        builder.replaceQueryParam("start", pager.getPrevStart());
        prevHref = builder.build(false).toUriString();
      }

      String nextHref = null;
      if (pager.getNextStart() != null) {
        builder.replaceQueryParam("start", pager.getNextStart());
        nextHref = builder.build(false).toUriString();
      }

      return new EntityCollectionResponseV2(
          pager,
          entities,
          fetch,
          BASE_URI + '/' + entityName,
          meta,
          permissionService,
          dataService,
          languageService,
          prevHref,
          nextHref);
    }
  }